hickory_server/zone_handler/
message_request.rs1use crate::{
9 proto::{
10 ProtoError,
11 op::{Edns, EmitAndCount, Header, LowerQuery, Message, Metadata, emit_message_parts},
12 rr::{Record, rdata::TSIG},
13 serialize::binary::{
14 BinDecodable, BinDecoder, BinEncodable, BinEncoder, DecodeError, NameEncoding,
15 },
16 },
17 zone_handler::LookupError,
18};
19
20#[derive(Debug, PartialEq)]
22pub struct MessageRequest {
23 pub metadata: Metadata,
25 pub queries: Queries,
27 pub answers: Vec<Record>,
29 pub authorities: Vec<Record>,
33 pub additionals: Vec<Record>,
35 pub signature: Option<Box<Record<TSIG>>>,
37 pub edns: Option<Edns>,
67}
68
69impl MessageRequest {
70 pub(crate) fn read(decoder: &mut BinDecoder<'_>, header: Header) -> Result<Self, DecodeError> {
73 let Header {
74 mut metadata,
75 counts,
76 } = header;
77 let queries = Queries::read(decoder, counts.queries as usize)?;
78 let (answers, _, _) =
79 Message::read_records(decoder, counts.answers as usize, false, metadata.op_code)?;
80 let (authorities, _, _) = Message::read_records(
81 decoder,
82 counts.authorities as usize,
83 false,
84 metadata.op_code,
85 )?;
86 let (additionals, edns, signature) =
87 Message::read_records(decoder, counts.additionals as usize, true, metadata.op_code)?;
88
89 if let Some(edns) = &edns {
91 let high_response_code = edns.rcode_high();
92 metadata.merge_response_code(high_response_code);
93 }
94
95 Ok(Self {
96 metadata,
97 queries,
98 answers,
99 authorities,
100 additionals,
101 signature,
102 edns,
103 })
104 }
105
106 #[cfg(any(test, feature = "testing"))]
110 pub fn mock(metadata: Metadata, query: impl Into<LowerQuery>) -> Self {
111 Self {
112 metadata,
113 queries: Queries::new(vec![query.into()]),
114 answers: Vec::new(),
115 authorities: Vec::new(),
116 additionals: Vec::new(),
117 signature: None,
118 edns: None,
119 }
120 }
121
122 pub fn max_payload(&self) -> u16 {
126 let max_size = self.edns.as_ref().map_or(512, Edns::max_payload);
127 if max_size < 512 { 512 } else { max_size }
128 }
129
130 pub fn version(&self) -> u8 {
134 self.edns.as_ref().map_or(0, Edns::version)
135 }
136}
137
138#[derive(Debug, PartialEq, Eq)]
140pub struct Queries {
141 queries: Vec<LowerQuery>,
142 original: Box<[u8]>,
143}
144
145impl Queries {
146 #[cfg(any(test, feature = "testing"))]
148 pub fn new(query: Vec<LowerQuery>) -> Self {
149 let mut encoded = Vec::new();
150 let mut encoder = BinEncoder::new(&mut encoded);
151 for q in query.iter() {
152 q.emit(&mut encoder).unwrap();
153 }
154 Self {
155 queries: query,
156 original: encoded.into_boxed_slice(),
157 }
158 }
159
160 pub fn read(decoder: &mut BinDecoder<'_>, num_queries: usize) -> Result<Self, DecodeError> {
162 let queries_start = decoder.index();
163 let mut queries = Vec::with_capacity(num_queries);
164 for _ in 0..num_queries {
165 queries.push(LowerQuery::read(decoder)?);
166 }
167
168 let original = decoder
169 .slice_from(queries_start)?
170 .to_vec()
171 .into_boxed_slice();
172
173 Ok(Self { queries, original })
174 }
175
176 pub fn len(&self) -> usize {
178 self.queries.len()
179 }
180
181 pub fn is_empty(&self) -> bool {
183 self.queries.is_empty()
184 }
185
186 pub fn queries(&self) -> &[LowerQuery] {
188 &self.queries
189 }
190
191 pub fn as_bytes(&self) -> &[u8] {
193 self.original.as_ref()
194 }
195
196 pub(crate) fn as_emit_and_count(&self) -> QueriesEmitAndCount<'_> {
197 QueriesEmitAndCount {
198 length: self.queries.len(),
199 first_query: self.queries.first(),
202 cached_serialized: self.original.as_ref(),
203 }
204 }
205
206 pub(crate) fn try_as_query(&self) -> Result<&LowerQuery, LookupError> {
209 let count = self.queries.len();
210 if count != 1 {
211 return Err(LookupError::BadQueryCount(count));
212 }
213 Ok(&self.queries[0])
214 }
215
216 pub(crate) fn empty() -> Self {
218 Self {
219 queries: Vec::new(),
220 original: (*b"").into(),
221 }
222 }
223}
224
225pub(crate) struct QueriesEmitAndCount<'q> {
226 length: usize,
228 first_query: Option<&'q LowerQuery>,
230 cached_serialized: &'q [u8],
232}
233
234impl EmitAndCount for QueriesEmitAndCount<'_> {
235 fn emit(&mut self, encoder: &mut BinEncoder<'_>) -> Result<usize, ProtoError> {
236 let original_offset = encoder.offset();
237 encoder.emit_vec(self.cached_serialized)?;
238 if matches!(encoder.name_encoding(), NameEncoding::Compressed) && self.first_query.is_some()
239 {
240 encoder.store_label_pointer(
241 original_offset,
242 original_offset + self.cached_serialized.len(),
243 )
244 }
245 Ok(self.length)
246 }
247}
248
249impl BinEncodable for MessageRequest {
250 fn emit(&self, encoder: &mut BinEncoder<'_>) -> Result<(), ProtoError> {
251 emit_message_parts(
252 &self.metadata,
253 &mut self.queries.queries.iter(),
256 &mut self.answers.iter(),
257 &mut self.authorities.iter(),
258 &mut self.additionals.iter(),
259 self.edns.as_ref(),
260 self.signature.as_deref(),
261 encoder,
262 )?;
263
264 Ok(())
265 }
266}
267
268pub trait UpdateRequest {
270 fn id(&self) -> u16;
272
273 fn zone(&self) -> Result<&LowerQuery, LookupError>;
275
276 fn prerequisites(&self) -> &[Record];
278
279 fn updates(&self) -> &[Record];
281
282 fn additionals(&self) -> &[Record];
284
285 fn signature(&self) -> Option<&Record<TSIG>>;
287}
288
289impl UpdateRequest for MessageRequest {
290 fn id(&self) -> u16 {
291 self.metadata.id
292 }
293
294 fn zone(&self) -> Result<&LowerQuery, LookupError> {
295 self.queries.try_as_query()
297 }
298
299 fn prerequisites(&self) -> &[Record] {
300 &self.answers
301 }
302
303 fn updates(&self) -> &[Record] {
304 &self.authorities
305 }
306
307 fn additionals(&self) -> &[Record] {
308 &self.additionals
309 }
310
311 fn signature(&self) -> Option<&Record<TSIG>> {
312 self.signature.as_deref()
313 }
314}