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}