1use crate::packet::{GenericMutablePacket, 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 match DnsResponsePacket::from_buf_mut(buf) {
1060 Some(pkt) => {
1061 packets.push(pkt);
1062 }
1063 _ => {
1064 break;
1065 }
1066 }
1067 }
1068 Some(packets)
1069 }
1070
1071 let mut working_buf = cursor;
1072
1073 let queries = parse_queries(query_count as usize, &mut working_buf)?;
1074 let responses = parse_responses(response_count as usize, &mut working_buf)?;
1075 let authorities = parse_responses(authority_rr_count as usize, &mut working_buf)?;
1076 let additionals = parse_responses(additional_rr_count as usize, &mut working_buf)?;
1077
1078 let payload = Bytes::copy_from_slice(working_buf);
1080
1081 Some(Self {
1082 header,
1083 queries,
1084 responses,
1085 authorities,
1086 additionals,
1087 payload,
1088 })
1089 }
1090
1091 fn from_bytes(mut bytes: Bytes) -> Option<Self> {
1092 Self::from_buf(&mut bytes)
1093 }
1094
1095 fn to_bytes(&self) -> Bytes {
1096 use bytes::{BufMut, BytesMut};
1097
1098 let mut buf = BytesMut::with_capacity(self.header_len() + self.payload.len());
1099
1100 let mut flags = 0u16;
1102 flags |= (self.header.is_response as u16) << 15;
1103 flags |= (self.header.opcode.value() as u16) << 11;
1104 flags |= (self.header.is_authoriative as u16) << 10;
1105 flags |= (self.header.is_truncated as u16) << 9;
1106 flags |= (self.header.is_recursion_desirable as u16) << 8;
1107 flags |= (self.header.is_recursion_available as u16) << 7;
1108 flags |= (self.header.zero_reserved as u16) << 6;
1109 flags |= (self.header.is_answer_authenticated as u16) << 5;
1110 flags |= (self.header.is_non_authenticated_data as u16) << 4;
1111 flags |= self.header.rcode.value() as u16;
1112
1113 buf.put_u16(self.header.id.into());
1114 buf.put_u16(flags);
1115 buf.put_u16(self.header.query_count.into());
1116 buf.put_u16(self.header.response_count.into());
1117 buf.put_u16(self.header.authority_rr_count.into());
1118 buf.put_u16(self.header.additional_rr_count.into());
1119
1120 for query in &self.queries {
1122 buf.extend_from_slice(&query.to_bytes());
1123 }
1124
1125 for response in &self.responses {
1127 buf.extend_from_slice(&response.to_bytes());
1128 }
1129
1130 for auth in &self.authorities {
1132 buf.extend_from_slice(&auth.to_bytes());
1133 }
1134
1135 for add in &self.additionals {
1137 buf.extend_from_slice(&add.to_bytes());
1138 }
1139
1140 Bytes::from(buf)
1141 }
1142
1143 fn header(&self) -> Bytes {
1144 self.to_bytes().slice(0..12)
1145 }
1146
1147 fn payload(&self) -> Bytes {
1148 self.payload.clone()
1149 }
1150
1151 fn header_len(&self) -> usize {
1152 12
1153 }
1154
1155 fn payload_len(&self) -> usize {
1156 self.payload.len()
1157 }
1158
1159 fn total_len(&self) -> usize {
1160 self.header_len() + self.payload_len()
1161 }
1162
1163 fn into_parts(self) -> (Self::Header, Bytes) {
1164 let header = ();
1165 let payload = self.payload;
1166 (header, payload)
1167 }
1168}
1169
1170pub struct DnsName(String);
1172
1173impl DnsName {
1174 pub fn from_bytes(buf: &[u8]) -> Result<Self, Utf8Error> {
1176 let mut pos = 0;
1177 let mut labels = Vec::new();
1178
1179 while pos < buf.len() {
1180 let len = buf[pos] as usize;
1181 if len == 0 {
1182 break;
1183 }
1184 pos += 1;
1185 if pos + len > buf.len() {
1186 break;
1187 }
1188 let label = std::str::from_utf8(&buf[pos..pos + len])?;
1189 labels.push(label);
1190 pos += len;
1191 }
1192
1193 Ok(DnsName(labels.join(".")))
1194 }
1195
1196 pub fn as_str(&self) -> &str {
1198 &self.0
1199 }
1200
1201 pub fn labels(&self) -> Vec<&str> {
1204 self.0.split('.').collect()
1205 }
1206}
1207
1208impl std::fmt::Display for DnsName {
1209 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1210 write!(f, "{}", self.0)
1211 }
1212}
1213
1214pub type MutableDnsPacket<'a> = GenericMutablePacket<'a, DnsPacket>;
1216
1217#[cfg(test)]
1218mod tests {
1219 use super::*;
1220 use crate::packet::MutablePacket;
1221
1222 #[test]
1223 fn test_dns_query() {
1224 let bytes = Bytes::from_static(&[
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, 0x00, 0x41, 0x00, 0x01, ]);
1228 let packet = DnsQueryPacket::from_bytes(bytes).unwrap();
1229 assert_eq!(
1230 packet.qname,
1231 vec![
1232 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,
1233 b'c', b'o', b'm', 0x00
1234 ]
1235 );
1236 assert_eq!(packet.qtype, DnsType::HTTPS);
1237 assert_eq!(packet.qclass, DnsClass::IN);
1238 }
1239
1240 #[test]
1241 fn test_dns_response() {
1242 let bytes = Bytes::from_static(&[
1243 0xc0, 0x0c, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x04, 0x0d, 0xe2, 0x02, 0x12, ]);
1250 let packet = DnsResponsePacket::from_bytes(bytes).unwrap();
1251 assert_eq!(packet.rtype, DnsType::A);
1252 assert_eq!(packet.rclass, DnsClass::IN);
1253 assert_eq!(packet.ttl, 60);
1254 assert_eq!(packet.data_len, 4);
1255 assert_eq!(packet.data, vec![13, 226, 2, 18]);
1256 }
1257
1258 #[test]
1259 fn test_dns_query_packet() {
1260 let bytes = Bytes::from_static(&[
1261 0x9b, 0xa0, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, b'_',
1262 b'l', b'd', b'a', b'p', 0x04, b'_', b't', b'c', b'p', 0x02, b'd', b'c', 0x06, b'_',
1263 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',
1264 b'I', b'V', b'A', b'T', b'E', 0x00, 0x00, 0x21, 0x00, 0x01,
1265 ]);
1266 let packet = DnsPacket::from_bytes(bytes).unwrap();
1267 assert_eq!(packet.header.id, 0x9ba0);
1268 assert_eq!(packet.header.is_response, 0);
1269 assert_eq!(packet.header.query_count, 1);
1270 assert_eq!(packet.queries.len(), 1);
1271 assert_eq!(
1272 packet.queries[0].get_qname_parsed().unwrap(),
1273 "_ldap._tcp.dc._msdcs.S4DOM.PRIVATE"
1274 );
1275 assert_eq!(packet.queries[0].qtype, DnsType::SRV);
1276 assert_eq!(packet.queries[0].qclass, DnsClass::IN);
1277 }
1278 #[test]
1279 fn test_dns_response_packet() {
1280 let bytes = Bytes::from_static(&[
1281 0xbc, 0x12, 0x85, 0x80, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x05, b's',
1282 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',
1283 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,
1284 0x00, 0x01, 0x00, 0x01, 0xc0, 0x0c, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x03, 0x84,
1285 0x00, 0x04, 0xc0, 0xa8, 0x7a, 0xbd,
1286 ]);
1287 let packet = DnsPacket::from_bytes(bytes).unwrap();
1288 assert_eq!(packet.header.id, 0xbc12);
1289 assert_eq!(packet.header.is_response, 1);
1290 assert_eq!(packet.header.query_count, 1);
1291 assert_eq!(packet.header.response_count, 1);
1292 assert_eq!(packet.queries.len(), 1);
1293 assert_eq!(
1294 packet.queries[0].get_qname_parsed().unwrap(),
1295 "s4dc1.samba.windows8.private"
1296 );
1297 assert_eq!(packet.queries[0].qtype, DnsType::A);
1298 assert_eq!(packet.responses[0].rtype, DnsType::A);
1299 assert_eq!(packet.responses[0].rclass, DnsClass::IN);
1300 assert_eq!(packet.responses[0].ttl, 900);
1301 assert_eq!(packet.responses[0].data_len, 4);
1302 assert_eq!(packet.responses[0].data, vec![192, 168, 122, 189]);
1303 }
1304
1305 #[test]
1306 fn test_mutable_dns_packet_header_edit() {
1307 let mut raw = [0u8; 16];
1308 raw[1] = 0x01; let mut packet = <MutableDnsPacket as MutablePacket>::new(&mut raw).expect("mutable dns");
1311 packet.header_mut()[0] = 0x12;
1312 packet.header_mut()[1] = 0x34;
1313 packet.payload_mut()[0] = 0xaa;
1314
1315 let frozen = packet.freeze().expect("freeze");
1316 assert_eq!(frozen.header.id, 0x1234);
1317 assert_eq!(frozen.payload[0], 0xaa);
1318 }
1319}