hickory_server/authority/
message_request.rs

1// Copyright 2015-2021 Benjamin Fry <benjaminfry@me.com>
2//
3// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
4// https://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
5// https://opensource.org/licenses/MIT>, at your option. This file may not be
6// copied, modified, or distributed except according to those terms.
7
8use crate::proto::{
9    ProtoError, ProtoErrorKind,
10    op::{
11        Edns, Header, LowerQuery, Message, MessageType, OpCode, ResponseCode,
12        message::{self, EmitAndCount},
13    },
14    rr::Record,
15    serialize::binary::{BinDecodable, BinDecoder, BinEncodable, BinEncoder},
16};
17
18/// A Message which captures the data from an inbound request
19#[derive(Debug, PartialEq)]
20pub struct MessageRequest {
21    header: Header,
22    queries: Queries,
23    answers: Vec<Record>,
24    name_servers: Vec<Record>,
25    additionals: Vec<Record>,
26    sig0: Vec<Record>,
27    edns: Option<Edns>,
28}
29
30impl MessageRequest {
31    /// Return the request header
32    pub fn header(&self) -> &Header {
33        &self.header
34    }
35
36    /// see `Header::id()`
37    pub fn id(&self) -> u16 {
38        self.header.id()
39    }
40
41    /// see `Header::message_type()`
42    pub fn message_type(&self) -> MessageType {
43        self.header.message_type()
44    }
45
46    /// see `Header::op_code()`
47    pub fn op_code(&self) -> OpCode {
48        self.header.op_code()
49    }
50
51    /// see `Header::authoritative()`
52    pub fn authoritative(&self) -> bool {
53        self.header.authoritative()
54    }
55
56    /// see `Header::truncated()`
57    pub fn truncated(&self) -> bool {
58        self.header.truncated()
59    }
60
61    /// see `Header::recursion_desired()`
62    pub fn recursion_desired(&self) -> bool {
63        self.header.recursion_desired()
64    }
65
66    /// see `Header::recursion_available()`
67    pub fn recursion_available(&self) -> bool {
68        self.header.recursion_available()
69    }
70
71    /// see `Header::authentic_data()`
72    pub fn authentic_data(&self) -> bool {
73        self.header.authentic_data()
74    }
75
76    /// see `Header::checking_disabled()`
77    pub fn checking_disabled(&self) -> bool {
78        self.header.checking_disabled()
79    }
80
81    /// # Return value
82    ///
83    /// The `ResponseCode`, if this is an EDNS message then this will join the section from the OPT
84    ///  record to create the EDNS `ResponseCode`
85    pub fn response_code(&self) -> ResponseCode {
86        self.header.response_code()
87    }
88
89    /// ```text
90    /// Question        Carries the query name and other query parameters.
91    /// ```
92    pub fn queries(&self) -> &[LowerQuery] {
93        &self.queries.queries
94    }
95
96    /// ```text
97    /// Answer          Carries RRs which directly answer the query.
98    /// ```
99    pub fn answers(&self) -> &[Record] {
100        &self.answers
101    }
102
103    /// ```text
104    /// Authority       Carries RRs which describe other authoritative servers.
105    ///                 May optionally carry the SOA RR for the authoritative
106    ///                 data in the answer section.
107    /// ```
108    pub fn name_servers(&self) -> &[Record] {
109        &self.name_servers
110    }
111
112    /// ```text
113    /// Additional      Carries RRs which may be helpful in using the RRs in the
114    ///                 other sections.
115    /// ```
116    pub fn additionals(&self) -> &[Record] {
117        &self.additionals
118    }
119
120    /// [RFC 6891, EDNS(0) Extensions, April 2013](https://tools.ietf.org/html/rfc6891#section-6.1.1)
121    ///
122    /// ```text
123    /// 6.1.1.  Basic Elements
124    ///
125    ///  An OPT pseudo-RR (sometimes called a meta-RR) MAY be added to the
126    ///  additional data section of a request.
127    ///
128    ///  The OPT RR has RR type 41.
129    ///
130    ///  If an OPT record is present in a received request, compliant
131    ///  responders MUST include an OPT record in their respective responses.
132    ///
133    ///  An OPT record does not carry any DNS data.  It is used only to
134    ///  contain control information pertaining to the question-and-answer
135    ///  sequence of a specific transaction.  OPT RRs MUST NOT be cached,
136    ///  forwarded, or stored in or loaded from zone files.
137    ///
138    ///  The OPT RR MAY be placed anywhere within the additional data section.
139    ///  When an OPT RR is included within any DNS message, it MUST be the
140    ///  only OPT RR in that message.  If a query message with more than one
141    ///  OPT RR is received, a FORMERR (RCODE=1) MUST be returned.  The
142    ///  placement flexibility for the OPT RR does not override the need for
143    ///  the TSIG or SIG(0) RRs to be the last in the additional section
144    ///  whenever they are present.
145    /// ```
146    /// # Return value
147    ///
148    /// Returns the EDNS record if it was found in the additional section.
149    pub fn edns(&self) -> Option<&Edns> {
150        self.edns.as_ref()
151    }
152
153    /// Any SIG0 records for signed messages
154    pub fn sig0(&self) -> &[Record] {
155        &self.sig0
156    }
157
158    /// # Return value
159    ///
160    /// the max payload value as it's defined in the EDNS section.
161    pub fn max_payload(&self) -> u16 {
162        let max_size = self.edns.as_ref().map_or(512, Edns::max_payload);
163        if max_size < 512 { 512 } else { max_size }
164    }
165
166    /// # Return value
167    ///
168    /// the version as defined in the EDNS record
169    pub fn version(&self) -> u8 {
170        self.edns.as_ref().map_or(0, Edns::version)
171    }
172
173    /// Returns the original queries received from the client
174    pub(crate) fn raw_queries(&self) -> &Queries {
175        &self.queries
176    }
177}
178
179impl<'q> BinDecodable<'q> for MessageRequest {
180    // TODO: generify this with Message?
181    /// Reads a MessageRequest from the decoder
182    fn read(decoder: &mut BinDecoder<'q>) -> Result<Self, ProtoError> {
183        let mut header = Header::read(decoder)?;
184
185        let mut try_parse_rest = move || {
186            // get all counts before header moves
187            let query_count = header.query_count() as usize;
188            let answer_count = header.answer_count() as usize;
189            let name_server_count = header.name_server_count() as usize;
190            let additional_count = header.additional_count() as usize;
191
192            let queries = Queries::read(decoder, query_count)?;
193            let (answers, _, _) = Message::read_records(decoder, answer_count, false)?;
194            let (name_servers, _, _) = Message::read_records(decoder, name_server_count, false)?;
195            let (additionals, edns, sig0) = Message::read_records(decoder, additional_count, true)?;
196
197            // need to grab error code from EDNS (which might have a higher value)
198            if let Some(edns) = &edns {
199                let high_response_code = edns.rcode_high();
200                header.merge_response_code(high_response_code);
201            }
202
203            Ok(Self {
204                header,
205                queries,
206                answers,
207                name_servers,
208                additionals,
209                sig0,
210                edns,
211            })
212        };
213
214        match try_parse_rest() {
215            Ok(message) => Ok(message),
216            Err(e) => Err(ProtoErrorKind::FormError {
217                header,
218                error: Box::new(e),
219            }
220            .into()),
221        }
222    }
223}
224
225/// A set of Queries with the associated serialized data
226#[derive(Debug, PartialEq, Eq)]
227pub struct Queries {
228    queries: Vec<LowerQuery>,
229    original: Box<[u8]>,
230}
231
232impl Queries {
233    fn read_queries(
234        decoder: &mut BinDecoder<'_>,
235        count: usize,
236    ) -> Result<Vec<LowerQuery>, ProtoError> {
237        let mut queries = Vec::with_capacity(count);
238        for _ in 0..count {
239            queries.push(LowerQuery::read(decoder)?);
240        }
241        Ok(queries)
242    }
243
244    /// Read queries from a decoder
245    pub fn read(decoder: &mut BinDecoder<'_>, num_queries: usize) -> Result<Self, ProtoError> {
246        let queries_start = decoder.index();
247        let queries = Self::read_queries(decoder, num_queries)?;
248        let original = decoder
249            .slice_from(queries_start)?
250            .to_vec()
251            .into_boxed_slice();
252
253        Ok(Self { queries, original })
254    }
255
256    /// return the number of queries in the request
257    pub fn len(&self) -> usize {
258        self.queries.len()
259    }
260
261    /// Returns true if there are no queries
262    pub fn is_empty(&self) -> bool {
263        self.queries.is_empty()
264    }
265
266    /// Returns the queries from the request
267    pub fn queries(&self) -> &[LowerQuery] {
268        &self.queries
269    }
270
271    /// returns the bytes as they were seen from the Client
272    pub fn as_bytes(&self) -> &[u8] {
273        self.original.as_ref()
274    }
275
276    pub(crate) fn as_emit_and_count(&self) -> QueriesEmitAndCount<'_> {
277        QueriesEmitAndCount {
278            length: self.queries.len(),
279            // We don't generally support more than one query, but this will at least give us one
280            // cache entry.
281            first_query: self.queries.first(),
282            cached_serialized: self.original.as_ref(),
283        }
284    }
285
286    /// Validate that this set of Queries contains exactly one Query, and return a reference to the
287    /// `LowerQuery` if so.
288    pub(crate) fn try_as_query(&self) -> Result<&LowerQuery, ProtoError> {
289        let count = self.queries.len();
290        if count != 1 {
291            return Err(ProtoErrorKind::BadQueryCount(count).into());
292        }
293        Ok(&self.queries[0])
294    }
295
296    /// Construct an empty set of queries
297    pub(crate) fn empty() -> Self {
298        Self {
299            queries: Vec::new(),
300            original: (*b"").into(),
301        }
302    }
303}
304
305pub(crate) struct QueriesEmitAndCount<'q> {
306    /// Number of queries in this segment
307    length: usize,
308    /// Use the first query, if it exists, to pre-populate the string compression cache
309    first_query: Option<&'q LowerQuery>,
310    /// The cached rendering of the original (wire-format) queries
311    cached_serialized: &'q [u8],
312}
313
314impl EmitAndCount for QueriesEmitAndCount<'_> {
315    fn emit(&mut self, encoder: &mut BinEncoder<'_>) -> Result<usize, ProtoError> {
316        let original_offset = encoder.offset();
317        encoder.emit_vec(self.cached_serialized)?;
318        if !encoder.is_canonical_names() && self.first_query.is_some() {
319            encoder.store_label_pointer(
320                original_offset,
321                original_offset + self.cached_serialized.len(),
322            )
323        }
324        Ok(self.length)
325    }
326}
327
328impl BinEncodable for MessageRequest {
329    fn emit(&self, encoder: &mut BinEncoder<'_>) -> Result<(), ProtoError> {
330        message::emit_message_parts(
331            &self.header,
332            // we emit the queries, not the raw bytes, in order to guarantee canonical form
333            //   in cases where that's necessary, like SIG0 validation
334            &mut self.queries.queries.iter(),
335            &mut self.answers.iter(),
336            &mut self.name_servers.iter(),
337            &mut self.additionals.iter(),
338            self.edns.as_ref(),
339            &self.sig0,
340            encoder,
341        )?;
342
343        Ok(())
344    }
345}
346
347/// A type which represents an MessageRequest for dynamic Update.
348pub trait UpdateRequest {
349    /// Id of the Message
350    fn id(&self) -> u16;
351
352    /// Zone being updated, this should be the query of a Message
353    fn zone(&self) -> Result<&LowerQuery, ProtoError>;
354
355    /// Prerequisites map to the answers of a Message
356    fn prerequisites(&self) -> &[Record];
357
358    /// Records to update map to the name_servers of a Message
359    fn updates(&self) -> &[Record];
360
361    /// Additional records
362    fn additionals(&self) -> &[Record];
363
364    /// SIG0 records for verifying the Message
365    fn sig0(&self) -> &[Record];
366}
367
368impl UpdateRequest for MessageRequest {
369    fn id(&self) -> u16 {
370        Self::id(self)
371    }
372
373    fn zone(&self) -> Result<&LowerQuery, ProtoError> {
374        // RFC 2136 says "the Zone Section is allowed to contain exactly one record."
375        self.raw_queries().try_as_query()
376    }
377
378    fn prerequisites(&self) -> &[Record] {
379        self.answers()
380    }
381
382    fn updates(&self) -> &[Record] {
383        self.name_servers()
384    }
385
386    fn additionals(&self) -> &[Record] {
387        self.additionals()
388    }
389
390    fn sig0(&self) -> &[Record] {
391        self.sig0()
392    }
393}