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}