1use alloc::vec::Vec;
4use alloc::string::String;
5
6use crate::rr::*;
7use crate::query::QueryBuf;
8
9pub(crate) fn read_u8(inp: &mut &[u8]) -> Result<u8, ()> {
10 let res = *inp.first().ok_or(())?;
11 *inp = &inp[1..];
12 Ok(res)
13}
14pub(crate) fn read_u16(inp: &mut &[u8]) -> Result<u16, ()> {
15 if inp.len() < 2 { return Err(()); }
16 let mut bytes = [0; 2];
17 bytes.copy_from_slice(&inp[..2]);
18 *inp = &inp[2..];
19 Ok(u16::from_be_bytes(bytes))
20}
21pub(crate) fn read_u32(inp: &mut &[u8]) -> Result<u32, ()> {
22 if inp.len() < 4 { return Err(()); }
23 let mut bytes = [0; 4];
24 bytes.copy_from_slice(&inp[..4]);
25 *inp = &inp[4..];
26 Ok(u32::from_be_bytes(bytes))
27}
28
29pub(crate) fn read_u8_len_prefixed_bytes(inp: &mut &[u8]) -> Result<Vec<u8>, ()> {
30 let len = *inp.first().ok_or(())?;
31 *inp = &inp[1..];
32 if inp.len() < len.into() { return Err(()); }
33 let mut res = Vec::with_capacity(len.into());
34 res.extend_from_slice(&inp[..len.into()]);
35 *inp = &inp[len.into()..];
36 Ok(res)
37}
38
39pub(crate) fn write_nsec_types_bitmap<W: Writer>(out: &mut W, types: &[u8; 8192]) {
40 for (idx, flags) in types.chunks(32).enumerate() {
41 debug_assert_eq!(flags.len(), 32);
42 if flags != [0; 32] {
43 let last_nonzero_idx = flags.iter().rposition(|flag| *flag != 0)
44 .unwrap_or_else(|| { debug_assert!(false); 0 });
45 out.write(&(idx as u8).to_be_bytes());
46 out.write(&(last_nonzero_idx as u8 + 1).to_be_bytes());
47 out.write(&flags[..last_nonzero_idx + 1]);
48 }
49 }
50}
51pub(crate) fn nsec_types_bitmap_len(types: &[u8; 8192]) -> u16 {
52 let mut total_len = 0;
53 for flags in types.chunks(32) {
54 debug_assert_eq!(flags.len(), 32);
55 if flags != [0; 32] {
56 total_len += 3 + flags.iter().rposition(|flag| *flag != 0)
57 .unwrap_or_else(|| { debug_assert!(false); 0 }) as u16;
58 }
59 }
60 total_len
61}
62
63pub(crate) fn read_nsec_types_bitmap(inp: &mut &[u8]) -> Result<[u8; 8192], ()> {
64 let mut res = [0; 8192];
65 while !inp.is_empty() {
66 let block = *inp.get(0).ok_or(())?;
67 let len = *inp.get(1).ok_or(())?;
68 *inp = &inp[2..];
69 if inp.len() < block as usize * 32 + len as usize { return Err(()); }
70 res[block as usize * 32..block as usize * 32 + len as usize]
71 .copy_from_slice(&inp[..len as usize]);
72 *inp = &inp[len as usize..];
73 }
74 Ok(res)
75}
76
77fn do_read_wire_packet_labels(inp: &mut &[u8], wire_packet: &[u8], name: &mut String, recursion_limit: usize) -> Result<(), ()> {
78 loop {
79 let len = read_u8(inp)? as usize;
80 if len == 0 {
81 if name.is_empty() { *name += "."; }
82 break;
83 } else if len >= 0xc0 && recursion_limit > 0 {
84 let offs = ((len & !0xc0) << 8) | read_u8(inp)? as usize;
85 if offs >= wire_packet.len() { return Err(()); }
86 do_read_wire_packet_labels(&mut &wire_packet[offs..], wire_packet, name, recursion_limit - 1)?;
87 break;
88 }
89 if inp.len() <= len { return Err(()); }
90 *name += core::str::from_utf8(&inp[..len]).map_err(|_| ())?;
91 *name += ".";
92 *inp = &inp[len..];
93 if name.len() > 255 { return Err(()); }
94 }
95 Ok(())
96}
97
98fn read_wire_packet_labels(inp: &mut &[u8], wire_packet: &[u8], name: &mut String) -> Result<(), ()> {
99 do_read_wire_packet_labels(inp, wire_packet, name, 255)
100}
101
102pub(crate) fn read_wire_packet_name(inp: &mut &[u8], wire_packet: &[u8]) -> Result<Name, ()> {
103 let mut name = String::with_capacity(1024);
104 read_wire_packet_labels(inp, wire_packet, &mut name)?;
105 name.try_into()
106}
107
108pub(crate) trait Writer { fn write(&mut self, buf: &[u8]); }
109impl Writer for Vec<u8> { fn write(&mut self, buf: &[u8]) { self.extend_from_slice(buf); } }
110impl Writer for QueryBuf { fn write(&mut self, buf: &[u8]) { self.extend_from_slice(buf); } }
111#[cfg(feature = "validation")]
112impl Writer for crate::crypto::hash::Hasher { fn write(&mut self, buf: &[u8]) { self.update(buf); } }
113pub(crate) fn write_name<W: Writer>(out: &mut W, name: &str) {
114 let canonical_name = name.to_ascii_lowercase();
115 if canonical_name == "." {
116 out.write(&[0]);
117 } else {
118 for label in canonical_name.split('.') {
119 out.write(&(label.len() as u8).to_be_bytes());
120 out.write(label.as_bytes());
121 }
122 }
123}
124pub(crate) fn name_len(name: &Name) -> u16 {
125 if name.as_str() == "." {
126 1
127 } else {
128 let mut res = 0;
129 for label in name.split('.') {
130 res += 1 + label.len();
131 }
132 res as u16
133 }
134}
135
136pub(crate) fn parse_wire_packet_rr(inp: &mut &[u8], wire_packet: &[u8]) -> Result<(RR, u32), ()> {
137 let name = read_wire_packet_name(inp, wire_packet)?;
138 let ty = read_u16(inp)?;
139 let class = read_u16(inp)?;
140 if class != 1 { return Err(()); } let ttl = read_u32(inp)?;
142 let data_len = read_u16(inp)? as usize;
143 if inp.len() < data_len { return Err(()); }
144 let data = &inp[..data_len];
145 *inp = &inp[data_len..];
146
147 let rr = match ty {
148 A::TYPE => RR::A(A::read_from_data(name, data, wire_packet)?),
149 AAAA::TYPE => RR::AAAA(AAAA::read_from_data(name, data, wire_packet)?),
150 NS::TYPE => RR::NS(NS::read_from_data(name, data, wire_packet)?),
151 Txt::TYPE => RR::Txt(Txt::read_from_data(name, data, wire_packet)?),
152 CName::TYPE => RR::CName(CName::read_from_data(name, data, wire_packet)?),
153 DName::TYPE => RR::DName(DName::read_from_data(name, data, wire_packet)?),
154 TLSA::TYPE => RR::TLSA(TLSA::read_from_data(name, data, wire_packet)?),
155 DnsKey::TYPE => RR::DnsKey(DnsKey::read_from_data(name, data, wire_packet)?),
156 DS::TYPE => RR::DS(DS::read_from_data(name, data, wire_packet)?),
157 RRSig::TYPE => RR::RRSig(RRSig::read_from_data(name, data, wire_packet)?),
158 NSec::TYPE => RR::NSec(NSec::read_from_data(name, data, wire_packet)?),
159 NSec3::TYPE => RR::NSec3(NSec3::read_from_data(name, data, wire_packet)?),
160 _ => return Err(()),
161 };
162 Ok((rr, ttl))
163}
164
165pub(crate) fn parse_rr(inp: &mut &[u8]) -> Result<RR, ()> {
166 parse_wire_packet_rr(inp, &[]).map(|(rr, _)| rr)
167}
168
169pub fn parse_rr_stream(mut inp: &[u8]) -> Result<Vec<RR>, ()> {
174 let mut res = Vec::with_capacity(32);
175 while !inp.is_empty() {
176 let rr = parse_rr(&mut inp)?;
177 #[cfg(fuzzing)]
178 let _ = rr.json(); res.push(rr);
180 }
181 Ok(res)
182}
183
184pub fn write_rr<RR: Record>(rr: &RR, ttl: u32, out: &mut Vec<u8>) {
189 write_name(out, rr.name());
190 out.extend_from_slice(&rr.ty().to_be_bytes());
191 out.extend_from_slice(&1u16.to_be_bytes()); out.extend_from_slice(&ttl.to_be_bytes());
193 rr.write_u16_len_prefixed_data(out);
194}