hickory_proto/op/
header.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
8//! Message metadata
9
10#[cfg(test)]
11use alloc::vec::Vec;
12use core::{convert::From, fmt};
13
14#[cfg(feature = "serde")]
15use serde::{Deserialize, Serialize};
16
17use crate::{
18    error::*,
19    op::{op_code::OpCode, response_code::ResponseCode},
20    serialize::binary::*,
21};
22
23/// Metadata for the `Message` struct.
24///
25/// [RFC 1035, DOMAIN NAMES - IMPLEMENTATION AND SPECIFICATION, November 1987](https://tools.ietf.org/html/rfc1035)
26///
27/// ```text
28/// 4.1.1. Header section format
29///
30/// The header contains the following fields
31///
32///                                    1  1  1  1  1  1
33///      0  1  2  3  4  5  6  7  8  9  0  1  2  3  4  5
34///     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
35///     |                      ID                       |
36///     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
37///     |QR|   Opcode  |AA|TC|RD|RA|ZZ|AD|CD|   RCODE   |  /// AD and CD from RFC4035
38///     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
39///     |                    QDCOUNT / ZCOUNT           |
40///     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
41///     |                    ANCOUNT / PRCOUNT          |
42///     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
43///     |                    NSCOUNT / UPCOUNT          |
44///     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
45///     |                    ARCOUNT / ADCOUNT          |
46///     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
47///
48/// where
49///
50/// Z               Reserved for future use.  Must be zero in all queries
51///                 and responses.
52///
53/// ```
54///
55#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Eq, Hash)]
56#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
57pub struct Header {
58    id: u16,
59    message_type: MessageType,
60    op_code: OpCode,
61    authoritative: bool,
62    truncation: bool,
63    recursion_desired: bool,
64    recursion_available: bool,
65    authentic_data: bool,
66    checking_disabled: bool,
67    response_code: ResponseCode,
68    query_count: u16,
69    answer_count: u16,
70    name_server_count: u16,
71    additional_count: u16,
72}
73
74impl fmt::Display for Header {
75    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
76        write!(
77            f,
78            "{id}:{message_type}:{flags}:{code:?}:{op_code}:{answers}/{authorities}/{additionals}",
79            id = self.id,
80            message_type = self.message_type,
81            flags = self.flags(),
82            code = self.response_code,
83            op_code = self.op_code,
84            answers = self.answer_count,
85            authorities = self.name_server_count,
86            additionals = self.additional_count,
87        )
88    }
89}
90
91/// Message types are either Query (also Update) or Response
92#[derive(Debug, PartialEq, Eq, PartialOrd, Copy, Clone, Hash)]
93#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
94pub enum MessageType {
95    /// Queries are Client requests, these are either Queries or Updates
96    Query,
97    /// Response message from the Server or upstream Resolver
98    Response,
99}
100
101impl fmt::Display for MessageType {
102    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
103        let s = match self {
104            Self::Query => "QUERY",
105            Self::Response => "RESPONSE",
106        };
107
108        f.write_str(s)
109    }
110}
111
112/// All the flags of the request/response header
113#[derive(Clone, Copy, PartialEq, Eq, Hash)]
114pub struct Flags {
115    authoritative: bool,
116    truncation: bool,
117    recursion_desired: bool,
118    recursion_available: bool,
119    authentic_data: bool,
120    checking_disabled: bool,
121}
122
123/// We are following the `dig` commands display format for the header flags
124///
125/// Example: "RD,AA,RA;" is Recursion-Desired, Authoritative-Answer, Recursion-Available.
126impl fmt::Display for Flags {
127    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
128        const SEPARATOR: &str = ",";
129
130        let flags = [
131            (self.recursion_desired, "RD"),
132            (self.checking_disabled, "CD"),
133            (self.truncation, "TC"),
134            (self.authoritative, "AA"),
135            (self.recursion_available, "RA"),
136            (self.authentic_data, "AD"),
137        ];
138
139        let mut iter = flags
140            .iter()
141            .cloned()
142            .filter_map(|(flag, s)| if flag { Some(s) } else { None });
143
144        // print first without a separator, then print the rest.
145        if let Some(s) = iter.next() {
146            f.write_str(s)?
147        }
148        for s in iter {
149            f.write_str(SEPARATOR)?;
150            f.write_str(s)?;
151        }
152
153        Ok(())
154    }
155}
156
157impl Default for Header {
158    fn default() -> Self {
159        Self::new()
160    }
161}
162
163impl Header {
164    // TODO: we should make id, message_type and op_code all required and non-editable
165    /// A default Header, not very useful.
166    pub const fn new() -> Self {
167        Self {
168            id: 0,
169            message_type: MessageType::Query,
170            op_code: OpCode::Query,
171            authoritative: false,
172            truncation: false,
173            recursion_desired: false,
174            recursion_available: false,
175            authentic_data: false,
176            checking_disabled: false,
177            response_code: ResponseCode::NoError,
178            query_count: 0,
179            answer_count: 0,
180            name_server_count: 0,
181            additional_count: 0,
182        }
183    }
184
185    /// Construct a new header based off the request header. This copies over the RD (recursion-desired)
186    ///   and CD (checking-disabled), as well as the op_code and id of the request.
187    ///
188    /// See <https://datatracker.ietf.org/doc/html/rfc6895#section-2>
189    ///
190    /// ```text
191    /// The AA, TC, RD, RA, and CD bits are each theoretically meaningful
192    ///    only in queries or only in responses, depending on the bit.  The AD
193    ///    bit was only meaningful in responses but is expected to have a
194    ///    separate but related meaning in queries (see Section 5.7 of
195    ///    [RFC6840]).  Only the RD and CD bits are expected to be copied from
196    ///    the query to the response; however, some DNS implementations copy all
197    ///    the query header as the initial value of the response header.  Thus,
198    ///    any attempt to use a "query" bit with a different meaning in a
199    ///    response or to define a query meaning for a "response" bit may be
200    ///    dangerous, given the existing implementation.  Meanings for these
201    ///    bits may only be assigned by a Standards Action.
202    /// ```
203    pub fn response_from_request(header: &Self) -> Self {
204        Self {
205            id: header.id,
206            message_type: MessageType::Response,
207            op_code: header.op_code,
208            authoritative: false,
209            truncation: false,
210            recursion_desired: header.recursion_desired,
211            recursion_available: false,
212            authentic_data: false,
213            checking_disabled: header.checking_disabled,
214            response_code: ResponseCode::default(),
215            query_count: 0,
216            answer_count: 0,
217            name_server_count: 0,
218            additional_count: 0,
219        }
220    }
221
222    /// Length of the header, always 12 bytes
223    #[inline(always)]
224    pub fn len() -> usize {
225        12 /* this is always 12 bytes */
226    }
227
228    /// Sets the id of the message, for queries this should be random.
229    pub fn set_id(&mut self, id: u16) -> &mut Self {
230        self.id = id;
231        self
232    }
233
234    /// Sets the message type, Queries and Updates both use Query.
235    pub fn set_message_type(&mut self, message_type: MessageType) -> &mut Self {
236        self.message_type = message_type;
237        self
238    }
239
240    /// Set the operation code for the message
241    pub fn set_op_code(&mut self, op_code: OpCode) -> &mut Self {
242        self.op_code = op_code;
243        self
244    }
245
246    /// From the server is specifies that it is an authoritative response.
247    pub fn set_authoritative(&mut self, authoritative: bool) -> &mut Self {
248        self.authoritative = authoritative;
249        self
250    }
251
252    /// Specifies that the records were too large for the payload.
253    ///
254    /// See EDNS or TCP for resolutions to truncation.
255    pub fn set_truncated(&mut self, truncated: bool) -> &mut Self {
256        self.truncation = truncated;
257        self
258    }
259
260    /// Specify that the resolver should recursively request data from upstream DNS nodes
261    pub fn set_recursion_desired(&mut self, recursion_desired: bool) -> &mut Self {
262        self.recursion_desired = recursion_desired;
263        self
264    }
265
266    /// Specifies that recursion is available from this or the remote resolver
267    pub fn set_recursion_available(&mut self, recursion_available: bool) -> &mut Self {
268        self.recursion_available = recursion_available;
269        self
270    }
271
272    /// Specifies that the data is authentic, i.e. the resolver believes all data to be valid through DNSSEC
273    pub fn set_authentic_data(&mut self, authentic_data: bool) -> &mut Self {
274        self.authentic_data = authentic_data;
275        self
276    }
277
278    /// Used during recursive resolution to specified if a resolver should or should not validate DNSSEC signatures
279    pub fn set_checking_disabled(&mut self, checking_disabled: bool) -> &mut Self {
280        self.checking_disabled = checking_disabled;
281        self
282    }
283
284    /// A method to get all header flags (useful for Display purposes)
285    pub fn flags(&self) -> Flags {
286        Flags {
287            authoritative: self.authoritative,
288            authentic_data: self.authentic_data,
289            checking_disabled: self.checking_disabled,
290            recursion_available: self.recursion_available,
291            recursion_desired: self.recursion_desired,
292            truncation: self.truncation,
293        }
294    }
295
296    /// The low response code (original response codes before EDNS extensions)
297    pub fn set_response_code(&mut self, response_code: ResponseCode) -> &mut Self {
298        self.response_code = response_code;
299        self
300    }
301
302    /// This combines the high and low response code values to form the complete ResponseCode from the EDNS record.
303    ///   The existing high order bits will be overwritten (if set), and `high_response_code` will be merge with
304    ///   the existing low order bits.
305    ///
306    /// This is intended for use during decoding.
307    #[doc(hidden)]
308    pub fn merge_response_code(&mut self, high_response_code: u8) {
309        self.response_code = ResponseCode::from(high_response_code, self.response_code.low());
310    }
311
312    /// Number or query records in the message
313    pub fn set_query_count(&mut self, query_count: u16) -> &mut Self {
314        self.query_count = query_count;
315        self
316    }
317
318    /// Number of answer records in the message
319    pub fn set_answer_count(&mut self, answer_count: u16) -> &mut Self {
320        self.answer_count = answer_count;
321        self
322    }
323
324    /// Number of name server records in the message
325    pub fn set_name_server_count(&mut self, name_server_count: u16) -> &mut Self {
326        self.name_server_count = name_server_count;
327        self
328    }
329
330    /// Number of additional records in the message
331    pub fn set_additional_count(&mut self, additional_count: u16) -> &mut Self {
332        self.additional_count = additional_count;
333        self
334    }
335
336    /// ```text
337    /// ID              A 16 bit identifier assigned by the program that
338    ///                 generates any kind of query.  This identifier is copied
339    ///                 the corresponding reply and can be used by the requester
340    ///                 to match up replies to outstanding queries.
341    /// ```
342    pub fn id(&self) -> u16 {
343        self.id
344    }
345
346    /// ```text
347    /// QR              A one bit field that specifies whether this message is a
348    ///                 query (0), or a response (1).
349    /// ```
350    pub fn message_type(&self) -> MessageType {
351        self.message_type
352    }
353
354    /// ```text
355    /// OPCODE          A four bit field that specifies kind of query in this
356    ///                 message.  This value is set by the originator of a query
357    ///                 and copied into the response.  The values are: <see super::op_code>
358    /// ```
359    pub fn op_code(&self) -> OpCode {
360        self.op_code
361    }
362
363    /// ```text
364    /// AA              Authoritative Answer - this bit is valid in responses,
365    ///                 and specifies that the responding name server is an
366    ///                 authority for the domain name in question section.
367    ///
368    ///                 Note that the contents of the answer section may have
369    ///                 multiple owner names because of aliases.  The AA bit
370    ///                 corresponds to the name which matches the query name, or
371    ///                 the first owner name in the answer section.
372    /// ```
373    pub fn authoritative(&self) -> bool {
374        self.authoritative
375    }
376
377    /// ```text
378    /// TC              TrunCation - specifies that this message was truncated
379    ///                 due to length greater than that permitted on the
380    ///                 transmission channel.
381    /// ```
382    pub fn truncated(&self) -> bool {
383        self.truncation
384    }
385
386    /// ```text
387    /// RD              Recursion Desired - this bit may be set in a query and
388    ///                 is copied into the response.  If RD is set, it directs
389    ///                 the name server to pursue the query recursively.
390    ///                 Recursive query support is optional.
391    /// ```
392    pub fn recursion_desired(&self) -> bool {
393        self.recursion_desired
394    }
395
396    /// ```text
397    /// RA              Recursion Available - this be is set or cleared in a
398    ///                 response, and denotes whether recursive query support is
399    ///                 available in the name server.
400    /// ```
401    pub fn recursion_available(&self) -> bool {
402        self.recursion_available
403    }
404
405    /// [RFC 4035, DNSSEC Resource Records, March 2005](https://tools.ietf.org/html/rfc4035#section-3.1.6)
406    ///
407    /// ```text
408    ///
409    /// 3.1.6.  The AD and CD Bits in an Authoritative Response
410    ///
411    ///   The CD and AD bits are designed for use in communication between
412    ///   security-aware resolvers and security-aware recursive name servers.
413    ///   These bits are for the most part not relevant to query processing by
414    ///   security-aware authoritative name servers.
415    ///
416    ///   A security-aware name server does not perform signature validation
417    ///   for authoritative data during query processing, even when the CD bit
418    ///   is clear.  A security-aware name server SHOULD clear the CD bit when
419    ///   composing an authoritative response.
420    ///
421    ///   A security-aware name server MUST NOT set the AD bit in a response
422    ///   unless the name server considers all RRsets in the Answer and
423    ///   Authority sections of the response to be authentic.  A security-aware
424    ///   name server's local policy MAY consider data from an authoritative
425    ///   zone to be authentic without further validation.  However, the name
426    ///   server MUST NOT do so unless the name server obtained the
427    ///   authoritative zone via secure means (such as a secure zone transfer
428    ///   mechanism) and MUST NOT do so unless this behavior has been
429    ///   configured explicitly.
430    ///
431    ///   A security-aware name server that supports recursion MUST follow the
432    ///   rules for the CD and AD bits given in Section 3.2 when generating a
433    ///   response that involves data obtained via recursion.
434    /// ```
435    pub fn authentic_data(&self) -> bool {
436        self.authentic_data
437    }
438
439    /// see `is_authentic_data()`
440    pub fn checking_disabled(&self) -> bool {
441        self.checking_disabled
442    }
443
444    /// ```text
445    /// RCODE           Response code - this 4 bit field is set as part of
446    ///                 responses.  The values have the following
447    ///                 interpretation: <see super::response_code>
448    /// ```
449    pub fn response_code(&self) -> ResponseCode {
450        self.response_code
451    }
452
453    /// ```text
454    /// QDCOUNT         an unsigned 16 bit integer specifying the number of
455    ///                 entries in the question section.
456    /// ```
457    ///
458    /// # Return value
459    ///
460    /// If this is a query, this will return the number of queries in the query section of the
461    //   message, for updates this represents the zone count (must be no more than 1).
462    pub fn query_count(&self) -> u16 {
463        self.query_count
464    }
465
466    /// ```text
467    /// ANCOUNT         an unsigned 16 bit integer specifying the number of
468    ///                 resource records in the answer section.
469    /// ```
470    ///
471    /// # Return value
472    ///
473    /// For query responses this is the number of records in the answer section, should be 0 for
474    ///  requests, for updates this is the count of prerequisite records.
475    pub fn answer_count(&self) -> u16 {
476        self.answer_count
477    }
478
479    /// for queries this is the nameservers which are authorities for the SOA of the Record
480    /// for updates this is the update record count
481    /// ```text
482    /// NSCOUNT         an unsigned 16 bit integer specifying the number of name
483    ///                 server resource records in the authority records
484    ///                 section.
485    /// ```
486    ///
487    /// # Return value
488    ///
489    /// For query responses this is the number of authorities, or nameservers, in the name server
490    ///  section, for updates this is the number of update records being sent.
491    pub fn name_server_count(&self) -> u16 {
492        self.name_server_count
493    }
494
495    /// ```text
496    /// ARCOUNT         an unsigned 16 bit integer specifying the number of
497    ///                 resource records in the additional records section.
498    /// ```
499    ///
500    /// # Return value
501    ///
502    /// This is the additional record section count, this section may include EDNS options.
503    pub fn additional_count(&self) -> u16 {
504        self.additional_count
505    }
506}
507
508impl BinEncodable for Header {
509    fn emit(&self, encoder: &mut BinEncoder<'_>) -> ProtoResult<()> {
510        encoder.reserve(12)?; // the 12 bytes for the following fields;
511
512        // Id
513        encoder.emit_u16(self.id)?;
514
515        // IsQuery, OpCode, Authoritative, Truncation, RecursionDesired
516        let mut q_opcd_a_t_r: u8 = if let MessageType::Response = self.message_type {
517            0x80
518        } else {
519            0x00
520        };
521        q_opcd_a_t_r |= u8::from(self.op_code) << 3;
522        q_opcd_a_t_r |= if self.authoritative { 0x4 } else { 0x0 };
523        q_opcd_a_t_r |= if self.truncation { 0x2 } else { 0x0 };
524        q_opcd_a_t_r |= if self.recursion_desired { 0x1 } else { 0x0 };
525        encoder.emit(q_opcd_a_t_r)?;
526
527        // IsRecursionAvailable, Triple 0's, ResponseCode
528        let mut r_z_ad_cd_rcod: u8 = if self.recursion_available {
529            0b1000_0000
530        } else {
531            0b0000_0000
532        };
533        r_z_ad_cd_rcod |= if self.authentic_data {
534            0b0010_0000
535        } else {
536            0b0000_0000
537        };
538        r_z_ad_cd_rcod |= if self.checking_disabled {
539            0b0001_0000
540        } else {
541            0b0000_0000
542        };
543        r_z_ad_cd_rcod |= self.response_code.low();
544        encoder.emit(r_z_ad_cd_rcod)?;
545
546        encoder.emit_u16(self.query_count)?;
547        encoder.emit_u16(self.answer_count)?;
548        encoder.emit_u16(self.name_server_count)?;
549        encoder.emit_u16(self.additional_count)?;
550
551        Ok(())
552    }
553}
554
555impl<'r> BinDecodable<'r> for Header {
556    fn read(decoder: &mut BinDecoder<'r>) -> ProtoResult<Self> {
557        let id = decoder.read_u16()?.unverified(/*it is valid for this to be any u16*/);
558
559        let q_opcd_a_t_r = decoder.pop()?.unverified(/*used as a bitfield, this is safe*/);
560        // if the first bit is set
561        let message_type = if (0b1000_0000 & q_opcd_a_t_r) == 0b1000_0000 {
562            MessageType::Response
563        } else {
564            MessageType::Query
565        };
566        // the 4bit opcode, masked and then shifted right 3bits for the u8...
567        let op_code = OpCode::from_u8((0b0111_1000 & q_opcd_a_t_r) >> 3);
568        let authoritative = (0b0000_0100 & q_opcd_a_t_r) == 0b0000_0100;
569        let truncation = (0b0000_0010 & q_opcd_a_t_r) == 0b0000_0010;
570        let recursion_desired = (0b0000_0001 & q_opcd_a_t_r) == 0b0000_0001;
571
572        let r_z_ad_cd_rcod = decoder.pop()?.unverified(/*used as a bitfield, this is safe*/); // fail fast...
573
574        let recursion_available = (0b1000_0000 & r_z_ad_cd_rcod) == 0b1000_0000;
575        let authentic_data = (0b0010_0000 & r_z_ad_cd_rcod) == 0b0010_0000;
576        let checking_disabled = (0b0001_0000 & r_z_ad_cd_rcod) == 0b0001_0000;
577        let response_code: u8 = 0b0000_1111 & r_z_ad_cd_rcod;
578        let response_code = ResponseCode::from_low(response_code);
579
580        // TODO: We should pass these restrictions on, they can't be trusted, but that would seriously complicate the Header type..
581        // TODO: perhaps the read methods for BinDecodable should return Restrict?
582        let query_count =
583            decoder.read_u16()?.unverified(/*this must be verified when reading queries*/);
584        let answer_count =
585            decoder.read_u16()?.unverified(/*this must be evaluated when reading records*/);
586        let name_server_count =
587            decoder.read_u16()?.unverified(/*this must be evaluated when reading records*/);
588        let additional_count =
589            decoder.read_u16()?.unverified(/*this must be evaluated when reading records*/);
590
591        // TODO: question, should this use the builder pattern instead? might be cleaner code, but
592        //  this guarantees that the Header is fully instantiated with all values...
593        Ok(Self {
594            id,
595            message_type,
596            op_code,
597            authoritative,
598            truncation,
599            recursion_desired,
600            recursion_available,
601            authentic_data,
602            checking_disabled,
603            response_code,
604            query_count,
605            answer_count,
606            name_server_count,
607            additional_count,
608        })
609    }
610}
611
612#[test]
613fn test_parse() {
614    let byte_vec = vec![
615        0x01, 0x10, 0xAA, 0x83, // 0b1010 1010 1000 0011
616        0x88, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11,
617    ];
618
619    let mut decoder = BinDecoder::new(&byte_vec);
620
621    let expect = Header {
622        id: 0x0110,
623        message_type: MessageType::Response,
624        op_code: OpCode::Update,
625        authoritative: false,
626        truncation: true,
627        recursion_desired: false,
628        recursion_available: true,
629        authentic_data: false,
630        checking_disabled: false,
631        response_code: ResponseCode::NXDomain,
632        query_count: 0x8877,
633        answer_count: 0x6655,
634        name_server_count: 0x4433,
635        additional_count: 0x2211,
636    };
637
638    let got = Header::read(&mut decoder).unwrap();
639
640    assert_eq!(got, expect);
641}
642
643#[test]
644fn test_write() {
645    let header = Header {
646        id: 0x0110,
647        message_type: MessageType::Response,
648        op_code: OpCode::Update,
649        authoritative: false,
650        truncation: true,
651        recursion_desired: false,
652        recursion_available: true,
653        authentic_data: false,
654        checking_disabled: false,
655        response_code: ResponseCode::NXDomain,
656        query_count: 0x8877,
657        answer_count: 0x6655,
658        name_server_count: 0x4433,
659        additional_count: 0x2211,
660    };
661
662    let expect: Vec<u8> = vec![
663        0x01, 0x10, 0xAA, 0x83, // 0b1010 1010 1000 0011
664        0x88, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11,
665    ];
666
667    let mut bytes = Vec::with_capacity(512);
668    {
669        let mut encoder = BinEncoder::new(&mut bytes);
670        header.emit(&mut encoder).unwrap();
671    }
672
673    assert_eq!(bytes, expect);
674}