1use crate::packet::Packet;
2use bytes::{BufMut, Bytes, BytesMut};
3use core::str;
4use nex_core::bitfield::{u1, u16be, u32be};
5use std::{
6 net::{IpAddr, Ipv4Addr, Ipv6Addr},
7 str::Utf8Error,
8};
9
10#[cfg(feature = "serde")]
11use serde::{Deserialize, Serialize};
12
13#[repr(u16)]
17#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
18#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
19pub enum DnsClass {
20 IN = 1, CS = 2, CH = 3, HS = 4, Unknown(u16),
25}
26
27impl DnsClass {
28 pub fn new(value: u16) -> Self {
29 match value {
30 1 => DnsClass::IN,
31 2 => DnsClass::CS,
32 3 => DnsClass::CH,
33 4 => DnsClass::HS,
34 v => DnsClass::Unknown(v),
35 }
36 }
37
38 pub fn value(&self) -> u16 {
39 match self {
40 DnsClass::IN => 1,
41 DnsClass::CS => 2,
42 DnsClass::CH => 3,
43 DnsClass::HS => 4,
44 DnsClass::Unknown(v) => *v,
45 }
46 }
47
48 pub fn name(&self) -> &'static str {
49 match self {
50 DnsClass::IN => "IN",
51 DnsClass::CS => "CS",
52 DnsClass::CH => "CH",
53 DnsClass::HS => "HS",
54 DnsClass::Unknown(_) => "Unknown",
55 }
56 }
57}
58
59#[allow(non_camel_case_types)]
60#[repr(u16)]
61#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
62#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
63pub enum DnsType {
64 A = 1,
65 NS = 2,
66 MD = 3,
67 MF = 4,
68 CNAME = 5,
69 SOA = 6,
70 MB = 7,
71 MG = 8,
72 MR = 9,
73 NULL = 10,
74 WKS = 11,
75 PTR = 12,
76 HINFO = 13,
77 MINFO = 14,
78 MX = 15,
79 TXT = 16,
80 RP = 17,
81 AFSDB = 18,
82 X25 = 19,
83 ISDN = 20,
84 RT = 21,
85 NSAP = 22,
86 NSAP_PTR = 23,
87 SIG = 24,
88 KEY = 25,
89 PX = 26,
90 GPOS = 27,
91 AAAA = 28,
92 LOC = 29,
93 NXT = 30,
94 EID = 31,
95 NIMLOC = 32,
96 SRV = 33,
97 ATMA = 34,
98 NAPTR = 35,
99 KX = 36,
100 CERT = 37,
101 A6 = 38,
102 DNAME = 39,
103 SINK = 40,
104 OPT = 41,
105 APL = 42,
106 DS = 43,
107 SSHFP = 44,
108 IPSECKEY = 45,
109 RRSIG = 46,
110 NSEC = 47,
111 DNSKEY = 48,
112 DHCID = 49,
113 NSEC3 = 50,
114 NSEC3PARAM = 51,
115 TLSA = 52,
116 SMIMEA = 53,
117 HIP = 55,
118 NINFO = 56,
119 RKEY = 57,
120 TALINK = 58,
121 CDS = 59,
122 CDNSKEY = 60,
123 OPENPGPKEY = 61,
124 CSYNC = 62,
125 ZONEMD = 63,
126 SVCB = 64,
127 HTTPS = 65,
128 SPF = 99,
129 UINFO = 100,
130 UID = 101,
131 GID = 102,
132 UNSPEC = 103,
133 NID = 104,
134 L32 = 105,
135 L64 = 106,
136 LP = 107,
137 EUI48 = 108,
138 EUI64 = 109,
139 TKEY = 249,
140 TSIG = 250,
141 IXFR = 251,
142 AXFR = 252,
143 MAILB = 253,
144 MAILA = 254,
145 ANY = 255,
146 URI = 256,
147 CAA = 257,
148 AVC = 258,
149 DOA = 259,
150 AMTRELAY = 260,
151 TA = 32768,
152 DLV = 32769,
153 Unknown(u16),
154}
155
156impl DnsType {
157 pub fn new(value: u16) -> Self {
158 match value {
159 1 => DnsType::A,
160 2 => DnsType::NS,
161 3 => DnsType::MD,
162 4 => DnsType::MF,
163 5 => DnsType::CNAME,
164 6 => DnsType::SOA,
165 7 => DnsType::MB,
166 8 => DnsType::MG,
167 9 => DnsType::MR,
168 10 => DnsType::NULL,
169 11 => DnsType::WKS,
170 12 => DnsType::PTR,
171 13 => DnsType::HINFO,
172 14 => DnsType::MINFO,
173 15 => DnsType::MX,
174 16 => DnsType::TXT,
175 17 => DnsType::RP,
176 18 => DnsType::AFSDB,
177 19 => DnsType::X25,
178 20 => DnsType::ISDN,
179 21 => DnsType::RT,
180 22 => DnsType::NSAP,
181 23 => DnsType::NSAP_PTR,
182 24 => DnsType::SIG,
183 25 => DnsType::KEY,
184 26 => DnsType::PX,
185 27 => DnsType::GPOS,
186 28 => DnsType::AAAA,
187 29 => DnsType::LOC,
188 30 => DnsType::NXT,
189 31 => DnsType::EID,
190 32 => DnsType::NIMLOC,
191 33 => DnsType::SRV,
192 34 => DnsType::ATMA,
193 35 => DnsType::NAPTR,
194 36 => DnsType::KX,
195 37 => DnsType::CERT,
196 38 => DnsType::A6,
197 39 => DnsType::DNAME,
198 40 => DnsType::SINK,
199 41 => DnsType::OPT,
200 42 => DnsType::APL,
201 43 => DnsType::DS,
202 44 => DnsType::SSHFP,
203 45 => DnsType::IPSECKEY,
204 46 => DnsType::RRSIG,
205 47 => DnsType::NSEC,
206 48 => DnsType::DNSKEY,
207 49 => DnsType::DHCID,
208 50 => DnsType::NSEC3,
209 51 => DnsType::NSEC3PARAM,
210 52 => DnsType::TLSA,
211 53 => DnsType::SMIMEA,
212 55 => DnsType::HIP,
213 56 => DnsType::NINFO,
214 57 => DnsType::RKEY,
215 58 => DnsType::TALINK,
216 59 => DnsType::CDS,
217 60 => DnsType::CDNSKEY,
218 61 => DnsType::OPENPGPKEY,
219 62 => DnsType::CSYNC,
220 63 => DnsType::ZONEMD,
221 64 => DnsType::SVCB,
222 65 => DnsType::HTTPS,
223 99 => DnsType::SPF,
224 100 => DnsType::UINFO,
225 101 => DnsType::UID,
226 102 => DnsType::GID,
227 103 => DnsType::UNSPEC,
228 104 => DnsType::NID,
229 105 => DnsType::L32,
230 106 => DnsType::L64,
231 107 => DnsType::LP,
232 108 => DnsType::EUI48,
233 109 => DnsType::EUI64,
234 249 => DnsType::TKEY,
235 250 => DnsType::TSIG,
236 251 => DnsType::IXFR,
237 252 => DnsType::AXFR,
238 253 => DnsType::MAILB,
239 254 => DnsType::MAILA,
240 255 => DnsType::ANY,
241 256 => DnsType::URI,
242 257 => DnsType::CAA,
243 258 => DnsType::AVC,
244 259 => DnsType::DOA,
245 260 => DnsType::AMTRELAY,
246 32768 => DnsType::TA,
247 32769 => DnsType::DLV,
248 v => DnsType::Unknown(v),
249 }
250 }
251
252 pub fn value(&self) -> u16 {
253 match self {
254 DnsType::A => 1,
255 DnsType::NS => 2,
256 DnsType::MD => 3,
257 DnsType::MF => 4,
258 DnsType::CNAME => 5,
259 DnsType::SOA => 6,
260 DnsType::MB => 7,
261 DnsType::MG => 8,
262 DnsType::MR => 9,
263 DnsType::NULL => 10,
264 DnsType::WKS => 11,
265 DnsType::PTR => 12,
266 DnsType::HINFO => 13,
267 DnsType::MINFO => 14,
268 DnsType::MX => 15,
269 DnsType::TXT => 16,
270 DnsType::RP => 17,
271 DnsType::AFSDB => 18,
272 DnsType::X25 => 19,
273 DnsType::ISDN => 20,
274 DnsType::RT => 21,
275 DnsType::NSAP => 22,
276 DnsType::NSAP_PTR => 23,
277 DnsType::SIG => 24,
278 DnsType::KEY => 25,
279 DnsType::PX => 26,
280 DnsType::GPOS => 27,
281 DnsType::AAAA => 28,
282 DnsType::LOC => 29,
283 DnsType::NXT => 30,
284 DnsType::EID => 31,
285 DnsType::NIMLOC => 32,
286 DnsType::SRV => 33,
287 DnsType::ATMA => 34,
288 DnsType::NAPTR => 35,
289 DnsType::KX => 36,
290 DnsType::CERT => 37,
291 DnsType::A6 => 38,
292 DnsType::DNAME => 39,
293 DnsType::SINK => 40,
294 DnsType::OPT => 41,
295 DnsType::APL => 42,
296 DnsType::DS => 43,
297 DnsType::SSHFP => 44,
298 DnsType::IPSECKEY => 45,
299 DnsType::RRSIG => 46,
300 DnsType::NSEC => 47,
301 DnsType::DNSKEY => 48,
302 DnsType::DHCID => 49,
303 DnsType::NSEC3 => 50,
304 DnsType::NSEC3PARAM => 51,
305 DnsType::TLSA => 52,
306 DnsType::SMIMEA => 53,
307 DnsType::HIP => 55,
308 DnsType::NINFO => 56,
309 DnsType::RKEY => 57,
310 DnsType::TALINK => 58,
311 DnsType::CDS => 59,
312 DnsType::CDNSKEY => 60,
313 DnsType::OPENPGPKEY => 61,
314 DnsType::CSYNC => 62,
315 DnsType::ZONEMD => 63,
316 DnsType::SVCB => 64,
317 DnsType::HTTPS => 65,
318 DnsType::SPF => 99,
319 DnsType::UINFO => 100,
320 DnsType::UID => 101,
321 DnsType::GID => 102,
322 DnsType::UNSPEC => 103,
323 DnsType::NID => 104,
324 DnsType::L32 => 105,
325 DnsType::L64 => 106,
326 DnsType::LP => 107,
327 DnsType::EUI48 => 108,
328 DnsType::EUI64 => 109,
329 DnsType::TKEY => 249,
330 DnsType::TSIG => 250,
331 DnsType::IXFR => 251,
332 DnsType::AXFR => 252,
333 DnsType::MAILB => 253,
334 DnsType::MAILA => 254,
335 DnsType::ANY => 255,
336 DnsType::URI => 256,
337 DnsType::CAA => 257,
338 DnsType::AVC => 258,
339 DnsType::DOA => 259,
340 DnsType::AMTRELAY => 260,
341 DnsType::TA => 32768,
342 DnsType::DLV => 32769,
343 DnsType::Unknown(v) => *v,
344 }
345 }
346
347 pub fn name(&self) -> &'static str {
348 match self {
349 DnsType::A => "A", DnsType::NS => "NS", DnsType::MD => "MD", DnsType::MF => "MF", DnsType::CNAME => "CNAME", DnsType::SOA => "SOA", DnsType::MB => "MB", DnsType::MG => "MG", DnsType::MR => "MR", DnsType::NULL => "NULL", DnsType::WKS => "WKS", DnsType::PTR => "PTR", DnsType::HINFO => "HINFO", DnsType::MINFO => "MINFO", DnsType::MX => "MX", DnsType::TXT => "TXT", DnsType::RP => "RP", DnsType::AFSDB => "AFSDB", DnsType::X25 => "X25", DnsType::ISDN => "ISDN", DnsType::RT => "RT", DnsType::NSAP => "NSAP", DnsType::NSAP_PTR => "NSAP_PTR", DnsType::SIG => "SIG", DnsType::KEY => "KEY", DnsType::PX => "PX", DnsType::GPOS => "GPOS", DnsType::AAAA => "AAAA", DnsType::LOC => "LOC", DnsType::NXT => "NXT", DnsType::EID => "EID", DnsType::NIMLOC => "NIMLOC", DnsType::SRV => "SRV", DnsType::ATMA => "ATMA", DnsType::NAPTR => "NAPTR", DnsType::KX => "KX", DnsType::CERT => "CERT", DnsType::A6 => "A6", DnsType::DNAME => "DNAME", DnsType::SINK => "SINK", DnsType::OPT => "OPT", DnsType::APL => "APL", DnsType::DS => "DS", DnsType::SSHFP => "SSHFP", DnsType::IPSECKEY => "IPSECKEY", DnsType::RRSIG => "RRSIG", DnsType::NSEC => "NSEC", DnsType::DNSKEY => "DNSKEY", DnsType::DHCID => "DHCID", DnsType::NSEC3 => "NSEC3", DnsType::NSEC3PARAM => "NSEC3PARAM", DnsType::TLSA => "TLSA", DnsType::SMIMEA => "SMIMEA", DnsType::HIP => "HIP", DnsType::NINFO => "NINFO", DnsType::RKEY => "RKEY", DnsType::TALINK => "TALINK", DnsType::CDS => "CDS", DnsType::CDNSKEY => "CDNSKEY", DnsType::OPENPGPKEY => "OPENPGPKEY", DnsType::CSYNC => "CSYNC", DnsType::ZONEMD => "ZONEMD", DnsType::SVCB => "SVCB", DnsType::HTTPS => "HTTPS", DnsType::SPF => "SPF", DnsType::UINFO => "UINFO", DnsType::UID => "UID", DnsType::GID => "GID", DnsType::UNSPEC => "UNSPEC", DnsType::NID => "NID", DnsType::L32 => "L32", DnsType::L64 => "L64", DnsType::LP => "LP", DnsType::EUI48 => "EUI48", DnsType::EUI64 => "EUI64", DnsType::TKEY => "TKEY", DnsType::TSIG => "TSIG", DnsType::IXFR => "IXFR", DnsType::AXFR => "AXFR", DnsType::MAILB => "MAILB", DnsType::MAILA => "MAILA", DnsType::ANY => "ANY", DnsType::URI => "URI", DnsType::CAA => "CAA", DnsType::AVC => "AVC", DnsType::DOA => "DOA", DnsType::AMTRELAY => "AMTRELAY", DnsType::TA => "TA", DnsType::DLV => "DLV", _ => "unknown",
439 }
440 }
441}
442
443#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
446#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
447pub enum OpCode {
448 Query,
449 InverseQuery,
450 Status,
451 Reserved,
452 Notify,
453 Update,
454 Dso,
455 Unassigned(u8),
456}
457
458impl OpCode {
459 pub fn new(value: u8) -> Self {
460 match value {
461 0 => Self::Query,
462 1 => Self::InverseQuery,
463 2 => Self::Status,
464 3 => Self::Reserved,
465 4 => Self::Notify,
466 5 => Self::Update,
467 6 => Self::Dso,
468 _ => Self::Unassigned(value),
469 }
470 }
471 pub fn value(&self) -> u8 {
472 match self {
473 Self::Query => 0,
474 Self::InverseQuery => 1,
475 Self::Status => 2,
476 Self::Reserved => 3,
477 Self::Notify => 4,
478 Self::Update => 5,
479 Self::Dso => 6,
480 Self::Unassigned(v) => *v,
481 }
482 }
483 pub fn name(&self) -> &'static str {
484 match self {
485 Self::Query => "Query",
486 Self::InverseQuery => "Inverse Query",
487 Self::Status => "Status",
488 Self::Reserved => "Reserved",
489 Self::Notify => "Notify",
490 Self::Update => "Update",
491 Self::Dso => "DSO",
492 Self::Unassigned(_) => "Unassigned",
493 }
494 }
495}
496
497#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
500#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
501pub enum RetCode {
502 NoError,
503 FormErr,
504 ServFail,
505 NXDomain,
506 NotImp,
507 Refused,
508 YXDomain,
509 YXRRSet,
510 NXRRSet,
511 NotAuth,
512 NotZone,
513 Dsotypeni,
514 BadVers,
515 BadKey,
516 BadTime,
517 BadMode,
518 BadName,
519 BadAlg,
520 BadTrunc,
521 BadCookie,
522 Unassigned(u8),
523}
524
525impl RetCode {
526 pub fn new(value: u8) -> Self {
527 match value {
528 0 => Self::NoError,
529 1 => Self::FormErr,
530 2 => Self::ServFail,
531 3 => Self::NXDomain,
532 4 => Self::NotImp,
533 5 => Self::Refused,
534 6 => Self::YXDomain,
535 7 => Self::YXRRSet,
536 8 => Self::NXRRSet,
537 9 => Self::NotAuth,
538 10 => Self::NotZone,
539 11 => Self::Dsotypeni,
540 12 => Self::BadVers,
541 13 => Self::BadKey,
542 14 => Self::BadTime,
543 15 => Self::BadMode,
544 16 => Self::BadName,
545 17 => Self::BadAlg,
546 18 => Self::BadTrunc,
547 19 => Self::BadCookie,
548 _ => Self::Unassigned(value),
549 }
550 }
551
552 pub fn value(&self) -> u8 {
553 match self {
554 Self::NoError => 0,
555 Self::FormErr => 1,
556 Self::ServFail => 2,
557 Self::NXDomain => 3,
558 Self::NotImp => 4,
559 Self::Refused => 5,
560 Self::YXDomain => 6,
561 Self::YXRRSet => 7,
562 Self::NXRRSet => 8,
563 Self::NotAuth => 9,
564 Self::NotZone => 10,
565 Self::Dsotypeni => 11,
566 Self::BadVers => 12,
567 Self::BadKey => 13,
568 Self::BadTime => 14,
569 Self::BadMode => 15,
570 Self::BadName => 16,
571 Self::BadAlg => 17,
572 Self::BadTrunc => 18,
573 Self::BadCookie => 19,
574 Self::Unassigned(v) => *v,
575 }
576 }
577
578 pub fn name(&self) -> &'static str {
579 match self {
580 RetCode::NoError => "No Error",
581 RetCode::FormErr => "Format Error",
582 RetCode::ServFail => "Server Failure",
583 RetCode::NXDomain => "Non-Existent Domain",
584 RetCode::NotImp => "Not Implemented",
585 RetCode::Refused => "Query Refused",
586 RetCode::YXDomain => "Name Exists When It Shouldn't",
587 RetCode::YXRRSet => "RR Set Exists When It Shouldn't",
588 RetCode::NXRRSet => "RR Set Doesn't Exist When It Should",
589 RetCode::NotAuth => "Not Authorized",
590 RetCode::NotZone => "Name Not Zone",
591 RetCode::Dsotypeni => "DSO Type NI",
592 RetCode::BadVers => "Bad Version",
593 RetCode::BadKey => "Bad Key",
594 RetCode::BadTime => "Bad Time",
595 RetCode::BadMode => "Bad Mode",
596 RetCode::BadName => "Bad Name",
597 RetCode::BadAlg => "Bad Algorithm",
598 RetCode::BadTrunc => "Bad Truncation",
599 RetCode::BadCookie => "Bad Cookie",
600 RetCode::Unassigned(_) => "Unassigned",
601 }
602 }
603}
604
605#[derive(Clone, Debug, PartialEq, Eq)]
607#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
608pub struct DnsQueryPacket {
609 pub qname: Vec<u8>,
610 pub qtype: DnsType,
611 pub qclass: DnsClass,
612 pub payload: Bytes,
613}
614
615impl Packet for DnsQueryPacket {
616 type Header = ();
617 fn from_buf(buf: &[u8]) -> Option<Self> {
618 let mut pos = 0;
619 let mut qname = Vec::new();
620
621 loop {
623 if pos >= buf.len() {
624 return None;
625 }
626
627 let len = buf[pos];
628 pos += 1;
629 qname.push(len);
630
631 if len == 0 {
632 break;
633 }
634
635 if pos + len as usize > buf.len() {
636 return None;
637 }
638
639 qname.extend_from_slice(&buf[pos..pos + len as usize]);
640 pos += len as usize;
641 }
642
643 if pos + 4 > buf.len() {
645 return None;
646 }
647
648 let qtype = DnsType::new(u16::from_be_bytes([buf[pos], buf[pos + 1]]));
649 let qclass = DnsClass::new(u16::from_be_bytes([buf[pos + 2], buf[pos + 3]]));
650 pos += 4;
651
652 let payload = Bytes::copy_from_slice(&buf[pos..]);
654
655 Some(Self {
656 qname,
657 qtype,
658 qclass,
659 payload,
660 })
661 }
662
663 fn from_bytes(mut bytes: Bytes) -> Option<Self> {
664 Self::from_buf(&mut bytes)
665 }
666
667 fn to_bytes(&self) -> Bytes {
668 let mut buf = BytesMut::with_capacity(self.qname.len() + 4);
669 buf.extend_from_slice(&self.qname);
670 buf.put_u16(self.qtype.value());
671 buf.put_u16(self.qclass.value());
672 buf.freeze()
673 }
674
675 fn header(&self) -> Bytes {
676 self.to_bytes().slice(0..self.header_len())
677 }
678
679 fn payload(&self) -> Bytes {
680 self.payload.clone()
681 }
682
683 fn header_len(&self) -> usize {
684 self.qname.len() + 4
685 }
686
687 fn payload_len(&self) -> usize {
688 self.payload.len()
689 }
690
691 fn total_len(&self) -> usize {
692 self.header_len() + self.payload_len()
693 }
694
695 fn into_parts(self) -> (Self::Header, Bytes) {
696 let header = ();
697 let payload = self.payload;
698 (header, payload)
699 }
700}
701
702impl DnsQueryPacket {
703 pub fn get_qname_parsed(&self) -> Result<String, Utf8Error> {
704 let name = &self.qname;
705 let mut qname = String::new();
706 let mut offset = 0;
707 loop {
708 let label_len = name[offset] as usize;
709 if label_len == 0 {
710 break;
711 }
712 if !qname.is_empty() {
713 qname.push('.');
714 }
715 match str::from_utf8(&name[offset + 1..offset + 1 + label_len]) {
716 Ok(label) => qname.push_str(label),
717 Err(e) => return Err(e),
718 }
719 offset += label_len + 1;
720 }
721 Ok(qname)
722 }
723 pub fn qname_length(&self) -> usize {
724 self.to_bytes().iter().take_while(|w| *w != &0).count() + 1
725 }
726 pub fn from_buf_mut(buf: &mut &[u8]) -> Option<Self> {
727 let mut qname = Vec::new();
728
729 loop {
730 if buf.is_empty() {
731 return None;
732 }
733 let len = buf[0];
734 *buf = &buf[1..];
735 qname.push(len);
736 if len == 0 {
737 break;
738 }
739 if buf.len() < len as usize {
740 return None;
741 }
742 qname.extend_from_slice(&buf[..len as usize]);
743 *buf = &buf[len as usize..];
744 }
745
746 if buf.len() < 4 {
747 return None;
748 }
749
750 let qtype = DnsType::new(u16::from_be_bytes([buf[0], buf[1]]));
751 *buf = &buf[2..];
752
753 let qclass = DnsClass::new(u16::from_be_bytes([buf[0], buf[1]]));
754 *buf = &buf[2..];
755
756 let payload = Bytes::copy_from_slice(buf);
757
758 Some(Self {
759 qname,
760 qtype,
761 qclass,
762 payload,
763 })
764 }
765}
766
767#[derive(Clone, Debug, PartialEq, Eq)]
769#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
770pub struct DnsResponsePacket {
771 pub name_tag: u16be,
772 pub rtype: DnsType,
773 pub rclass: DnsClass,
774 pub ttl: u32be,
775 pub data_len: u16be,
776 pub data: Vec<u8>,
777 pub payload: Bytes,
778}
779
780impl Packet for DnsResponsePacket {
781 type Header = ();
782 fn from_buf(buf: &[u8]) -> Option<Self> {
783 if buf.len() < 12 {
784 return None;
785 }
786
787 let mut pos = 0;
788
789 let name_tag = u16::from_be_bytes([buf[pos], buf[pos + 1]]).into();
790 pos += 2;
791
792 let rtype = DnsType::new(u16::from_be_bytes([buf[pos], buf[pos + 1]]));
793 pos += 2;
794
795 let rclass = DnsClass::new(u16::from_be_bytes([buf[pos], buf[pos + 1]]));
796 pos += 2;
797
798 let ttl = u32::from_be_bytes([buf[pos], buf[pos + 1], buf[pos + 2], buf[pos + 3]]).into();
799 pos += 4;
800
801 let data_len = u16::from_be_bytes([buf[pos], buf[pos + 1]]).into();
802 pos += 2;
803
804 let data_len_usize = data_len as usize;
805
806 if buf.len() < pos + data_len_usize {
807 return None;
808 }
809
810 let data = buf[pos..pos + data_len_usize].to_vec();
811 pos += data_len_usize;
812
813 let payload = Bytes::copy_from_slice(&buf[pos..]);
814
815 Some(Self {
816 name_tag,
817 rtype,
818 rclass,
819 ttl,
820 data_len,
821 data,
822 payload,
823 })
824 }
825 fn from_bytes(mut bytes: Bytes) -> Option<Self> {
826 Self::from_buf(&mut bytes)
827 }
828
829 fn to_bytes(&self) -> Bytes {
830 let mut buf = bytes::BytesMut::with_capacity(self.total_len());
831
832 buf.put_u16(self.name_tag.into());
833 buf.put_u16(self.rtype.value());
834 buf.put_u16(self.rclass.value());
835 buf.put_u32(self.ttl.into());
836 buf.put_u16(self.data_len.into());
837 buf.put_slice(&self.data);
838
839 buf.freeze()
840 }
841
842 fn header(&self) -> Bytes {
843 self.to_bytes().slice(0..self.total_len())
844 }
845
846 fn payload(&self) -> Bytes {
847 self.payload.clone()
848 }
849
850 fn header_len(&self) -> usize {
851 12
852 }
853
854 fn payload_len(&self) -> usize {
855 self.payload.len()
856 }
857
858 fn total_len(&self) -> usize {
859 self.header_len() + self.payload_len()
860 }
861
862 fn into_parts(self) -> (Self::Header, Bytes) {
863 let header = ();
864 let payload = self.payload;
865 (header, payload)
866 }
867}
868
869impl DnsResponsePacket {
870 pub fn from_buf_mut(buf: &mut &[u8]) -> Option<Self> {
872 if buf.len() < 12 {
873 return None;
874 }
875
876 let name_tag = u16::from_be_bytes([buf[0], buf[1]]).into();
878 *buf = &buf[2..];
879
880 let rtype = DnsType::new(u16::from_be_bytes([buf[0], buf[1]]));
882 *buf = &buf[2..];
883
884 let rclass = DnsClass::new(u16::from_be_bytes([buf[0], buf[1]]));
886 *buf = &buf[2..];
887
888 let ttl = u32::from_be_bytes([buf[0], buf[1], buf[2], buf[3]]).into();
890 *buf = &buf[4..];
891
892 let data_len = u16::from_be_bytes([buf[0], buf[1]]);
894 *buf = &buf[2..];
895
896 let safe_data_len = std::cmp::min(buf.len(), data_len as usize);
897 let data = buf[..safe_data_len].to_vec();
898 *buf = &buf[safe_data_len..];
899
900 let payload = Bytes::copy_from_slice(buf);
902
903 Some(Self {
904 name_tag,
905 rtype,
906 rclass,
907 ttl,
908 data_len: data_len.into(),
909 data,
910 payload,
911 })
912 }
913
914 pub fn get_ipv4(&self) -> Option<Ipv4Addr> {
916 if self.rtype == DnsType::A && self.data.len() == 4 {
917 Some(Ipv4Addr::new(
918 self.data[0],
919 self.data[1],
920 self.data[2],
921 self.data[3],
922 ))
923 } else {
924 None
925 }
926 }
927 pub fn get_ipv6(&self) -> Option<Ipv6Addr> {
929 if self.rtype == DnsType::AAAA && self.data.len() == 16 {
930 Some(Ipv6Addr::from(<[u8; 16]>::try_from(&self.data[..]).ok()?))
931 } else {
932 None
933 }
934 }
935
936 pub fn get_ip(&self) -> Option<IpAddr> {
938 match self.rtype {
939 DnsType::A => self.get_ipv4().map(IpAddr::V4),
940 DnsType::AAAA => self.get_ipv6().map(IpAddr::V6),
941 _ => None,
942 }
943 }
944
945 pub fn get_name(&self) -> Option<DnsName> {
947 match self.rtype {
948 DnsType::CNAME | DnsType::NS | DnsType::PTR => DnsName::from_bytes(&self.data).ok(),
949 _ => None,
950 }
951 }
952
953 pub fn get_txt_strings(&self) -> Option<Vec<String>> {
955 if self.rtype != DnsType::TXT {
956 return None;
957 }
958
959 let mut pos = 0;
960 let mut result = Vec::new();
961
962 while pos < self.data.len() {
963 let len = self.data[pos] as usize;
964 pos += 1;
965 if pos + len > self.data.len() {
966 break;
967 }
968
969 match std::str::from_utf8(&self.data[pos..pos + len]) {
970 Ok(s) => result.push(s.to_string()),
971 Err(_) => return None,
972 }
973
974 pos += len;
975 }
976
977 Some(result)
978 }
979}
980
981#[derive(Clone, Debug, PartialEq, Eq)]
982#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
983pub struct DnsHeader {
984 pub id: u16be,
985 pub is_response: u1,
986 pub opcode: OpCode,
987 pub is_authoriative: u1,
988 pub is_truncated: u1,
989 pub is_recursion_desirable: u1,
990 pub is_recursion_available: u1,
991 pub zero_reserved: u1,
992 pub is_answer_authenticated: u1,
993 pub is_non_authenticated_data: u1,
994 pub rcode: RetCode,
995 pub query_count: u16be,
996 pub response_count: u16be,
997 pub authority_rr_count: u16be,
998 pub additional_rr_count: u16be,
999}
1000
1001#[derive(Clone, Debug, PartialEq, Eq)]
1004pub struct DnsPacket {
1005 pub header: DnsHeader,
1006 pub queries: Vec<DnsQueryPacket>,
1007 pub responses: Vec<DnsResponsePacket>,
1008 pub authorities: Vec<DnsResponsePacket>,
1009 pub additionals: Vec<DnsResponsePacket>,
1010 pub payload: Bytes,
1011}
1012
1013impl Packet for DnsPacket {
1014 type Header = ();
1015 fn from_buf(buf: &[u8]) -> Option<Self> {
1016 if buf.len() < 12 {
1017 return None;
1018 }
1019
1020 let mut cursor = buf;
1021
1022 let id = u16::from_be_bytes([cursor[0], cursor[1]]);
1024 let flags = u16::from_be_bytes([cursor[2], cursor[3]]);
1025 let query_count = u16::from_be_bytes([cursor[4], cursor[5]]);
1026 let response_count = u16::from_be_bytes([cursor[6], cursor[7]]);
1027 let authority_rr_count = u16::from_be_bytes([cursor[8], cursor[9]]);
1028 let additional_rr_count = u16::from_be_bytes([cursor[10], cursor[11]]);
1029 cursor = &cursor[12..];
1030
1031 let header = DnsHeader {
1032 id: id.into(),
1033 is_response: ((flags >> 15) & 0x1) as u8,
1034 opcode: OpCode::new(((flags >> 11) & 0xF) as u8),
1035 is_authoriative: ((flags >> 10) & 0x1) as u8,
1036 is_truncated: ((flags >> 9) & 0x1) as u8,
1037 is_recursion_desirable: ((flags >> 8) & 0x1) as u8,
1038 is_recursion_available: ((flags >> 7) & 0x1) as u8,
1039 zero_reserved: ((flags >> 6) & 0x1) as u8,
1040 is_answer_authenticated: ((flags >> 5) & 0x1) as u8,
1041 is_non_authenticated_data: ((flags >> 4) & 0x1) as u8,
1042 rcode: RetCode::new((flags & 0xF) as u8),
1043 query_count: query_count.into(),
1044 response_count: response_count.into(),
1045 authority_rr_count: authority_rr_count.into(),
1046 additional_rr_count: additional_rr_count.into(),
1047 };
1048
1049 fn parse_queries(count: usize, buf: &mut &[u8]) -> Option<Vec<DnsQueryPacket>> {
1051 (0..count)
1052 .map(|_| DnsQueryPacket::from_buf_mut(buf))
1053 .collect()
1054 }
1055
1056 fn parse_responses(count: usize, buf: &mut &[u8]) -> Option<Vec<DnsResponsePacket>> {
1057 let mut packets = Vec::with_capacity(count);
1058 for _ in 0..count {
1059 if let Some(pkt) = DnsResponsePacket::from_buf_mut(buf) {
1060 packets.push(pkt);
1061 } else {
1062 break;
1063 }
1064 }
1065 Some(packets)
1066 }
1067
1068 let mut working_buf = cursor;
1069
1070 let queries = parse_queries(query_count as usize, &mut working_buf)?;
1071 let responses = parse_responses(response_count as usize, &mut working_buf)?;
1072 let authorities = parse_responses(authority_rr_count as usize, &mut working_buf)?;
1073 let additionals = parse_responses(additional_rr_count as usize, &mut working_buf)?;
1074
1075 let payload = Bytes::copy_from_slice(working_buf);
1077
1078 Some(Self {
1079 header,
1080 queries,
1081 responses,
1082 authorities,
1083 additionals,
1084 payload,
1085 })
1086 }
1087
1088 fn from_bytes(mut bytes: Bytes) -> Option<Self> {
1089 Self::from_buf(&mut bytes)
1090 }
1091
1092 fn to_bytes(&self) -> Bytes {
1093 use bytes::{BufMut, BytesMut};
1094
1095 let mut buf = BytesMut::with_capacity(self.header_len() + self.payload.len());
1096
1097 let mut flags = 0u16;
1099 flags |= (self.header.is_response as u16) << 15;
1100 flags |= (self.header.opcode.value() as u16) << 11;
1101 flags |= (self.header.is_authoriative as u16) << 10;
1102 flags |= (self.header.is_truncated as u16) << 9;
1103 flags |= (self.header.is_recursion_desirable as u16) << 8;
1104 flags |= (self.header.is_recursion_available as u16) << 7;
1105 flags |= (self.header.zero_reserved as u16) << 6;
1106 flags |= (self.header.is_answer_authenticated as u16) << 5;
1107 flags |= (self.header.is_non_authenticated_data as u16) << 4;
1108 flags |= self.header.rcode.value() as u16;
1109
1110 buf.put_u16(self.header.id.into());
1111 buf.put_u16(flags);
1112 buf.put_u16(self.header.query_count.into());
1113 buf.put_u16(self.header.response_count.into());
1114 buf.put_u16(self.header.authority_rr_count.into());
1115 buf.put_u16(self.header.additional_rr_count.into());
1116
1117 for query in &self.queries {
1119 buf.extend_from_slice(&query.to_bytes());
1120 }
1121
1122 for response in &self.responses {
1124 buf.extend_from_slice(&response.to_bytes());
1125 }
1126
1127 for auth in &self.authorities {
1129 buf.extend_from_slice(&auth.to_bytes());
1130 }
1131
1132 for add in &self.additionals {
1134 buf.extend_from_slice(&add.to_bytes());
1135 }
1136
1137 Bytes::from(buf)
1138 }
1139
1140 fn header(&self) -> Bytes {
1141 self.to_bytes().slice(0..12)
1142 }
1143
1144 fn payload(&self) -> Bytes {
1145 self.payload.clone()
1146 }
1147
1148 fn header_len(&self) -> usize {
1149 12
1150 }
1151
1152 fn payload_len(&self) -> usize {
1153 self.payload.len()
1154 }
1155
1156 fn total_len(&self) -> usize {
1157 self.header_len() + self.payload_len()
1158 }
1159
1160 fn into_parts(self) -> (Self::Header, Bytes) {
1161 let header = ();
1162 let payload = self.payload;
1163 (header, payload)
1164 }
1165}
1166
1167pub struct DnsName(String);
1169
1170impl DnsName {
1171 pub fn from_bytes(buf: &[u8]) -> Result<Self, Utf8Error> {
1173 let mut pos = 0;
1174 let mut labels = Vec::new();
1175
1176 while pos < buf.len() {
1177 let len = buf[pos] as usize;
1178 if len == 0 {
1179 break;
1180 }
1181 pos += 1;
1182 if pos + len > buf.len() {
1183 break;
1184 }
1185 let label = std::str::from_utf8(&buf[pos..pos + len])?;
1186 labels.push(label);
1187 pos += len;
1188 }
1189
1190 Ok(DnsName(labels.join(".")))
1191 }
1192
1193 pub fn as_str(&self) -> &str {
1195 &self.0
1196 }
1197
1198 pub fn labels(&self) -> Vec<&str> {
1201 self.0.split('.').collect()
1202 }
1203}
1204
1205impl std::fmt::Display for DnsName {
1206 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1207 write!(f, "{}", self.0)
1208 }
1209}
1210
1211#[cfg(test)]
1212mod tests {
1213 use super::*;
1214
1215 #[test]
1216 fn test_dns_query() {
1217 let bytes = Bytes::from_static(&[
1218 0x07, b'b', b'e', b'a', b'c', b'o', b'n', b's', 0x04, b'g', b'v', b't', b'2', 0x03,
1219 b'c', b'o', b'm', 0x00, 0x00, 0x41, 0x00, 0x01, ]);
1221 let packet = DnsQueryPacket::from_bytes(bytes).unwrap();
1222 assert_eq!(
1223 packet.qname,
1224 vec![
1225 0x07, b'b', b'e', b'a', b'c', b'o', b'n', b's', 0x04, b'g', b'v', b't', b'2', 0x03,
1226 b'c', b'o', b'm', 0x00
1227 ]
1228 );
1229 assert_eq!(packet.qtype, DnsType::HTTPS);
1230 assert_eq!(packet.qclass, DnsClass::IN);
1231 }
1232
1233 #[test]
1234 fn test_dns_response() {
1235 let bytes = Bytes::from_static(&[
1236 0xc0, 0x0c, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x04, 0x0d, 0xe2, 0x02, 0x12, ]);
1243 let packet = DnsResponsePacket::from_bytes(bytes).unwrap();
1244 assert_eq!(packet.rtype, DnsType::A);
1245 assert_eq!(packet.rclass, DnsClass::IN);
1246 assert_eq!(packet.ttl, 60);
1247 assert_eq!(packet.data_len, 4);
1248 assert_eq!(packet.data, vec![13, 226, 2, 18]);
1249 }
1250
1251 #[test]
1252 fn test_dns_query_packet() {
1253 let bytes = Bytes::from_static(&[
1254 0x9b, 0xa0, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, b'_',
1255 b'l', b'd', b'a', b'p', 0x04, b'_', b't', b'c', b'p', 0x02, b'd', b'c', 0x06, b'_',
1256 b'm', b's', b'd', b'c', b's', 0x05, b'S', b'4', b'D', b'O', b'M', 0x07, b'P', b'R',
1257 b'I', b'V', b'A', b'T', b'E', 0x00, 0x00, 0x21, 0x00, 0x01,
1258 ]);
1259 let packet = DnsPacket::from_bytes(bytes).unwrap();
1260 assert_eq!(packet.header.id, 0x9ba0);
1261 assert_eq!(packet.header.is_response, 0);
1262 assert_eq!(packet.header.query_count, 1);
1263 assert_eq!(packet.queries.len(), 1);
1264 assert_eq!(
1265 packet.queries[0].get_qname_parsed().unwrap(),
1266 "_ldap._tcp.dc._msdcs.S4DOM.PRIVATE"
1267 );
1268 assert_eq!(packet.queries[0].qtype, DnsType::SRV);
1269 assert_eq!(packet.queries[0].qclass, DnsClass::IN);
1270 }
1271 #[test]
1272 fn test_dns_response_packet() {
1273 let bytes = Bytes::from_static(&[
1274 0xbc, 0x12, 0x85, 0x80, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x05, b's',
1275 b'4', b'd', b'c', b'1', 0x05, b's', b'a', b'm', b'b', b'a', 0x08, b'w', b'i', b'n',
1276 b'd', b'o', b'w', b's', b'8', 0x07, b'p', b'r', b'i', b'v', b'a', b't', b'e', 0x00,
1277 0x00, 0x01, 0x00, 0x01, 0xc0, 0x0c, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x03, 0x84,
1278 0x00, 0x04, 0xc0, 0xa8, 0x7a, 0xbd,
1279 ]);
1280 let packet = DnsPacket::from_bytes(bytes).unwrap();
1281 assert_eq!(packet.header.id, 0xbc12);
1282 assert_eq!(packet.header.is_response, 1);
1283 assert_eq!(packet.header.query_count, 1);
1284 assert_eq!(packet.header.response_count, 1);
1285 assert_eq!(packet.queries.len(), 1);
1286 assert_eq!(
1287 packet.queries[0].get_qname_parsed().unwrap(),
1288 "s4dc1.samba.windows8.private"
1289 );
1290 assert_eq!(packet.queries[0].qtype, DnsType::A);
1291 assert_eq!(packet.responses[0].rtype, DnsType::A);
1292 assert_eq!(packet.responses[0].rclass, DnsClass::IN);
1293 assert_eq!(packet.responses[0].ttl, 900);
1294 assert_eq!(packet.responses[0].data_len, 4);
1295 assert_eq!(packet.responses[0].data, vec![192, 168, 122, 189]);
1296 }
1297}