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