trust_dns_proto/rr/
record_data.rs

1// Copyright 2015-2021 Benjamin Fry <benjaminfry@me.com>
2//
3// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
4// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
5// http://opensource.org/licenses/MIT>, at your option. This file may not be
6// copied, modified, or distributed except according to those terms.
7
8//! record data enum variants
9#![allow(deprecated, clippy::use_self)] // allows us to deprecate RData types
10
11use std::cmp::Ordering;
12#[cfg(test)]
13use std::convert::From;
14use std::fmt;
15use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
16
17#[cfg(feature = "serde-config")]
18use serde::{Deserialize, Serialize};
19
20use enum_as_inner::EnumAsInner;
21use tracing::{trace, warn};
22
23use super::domain::Name;
24use super::rdata;
25use super::rdata::{
26    CAA, CSYNC, HINFO, MX, NAPTR, NULL, OPENPGPKEY, OPT, SOA, SRV, SSHFP, SVCB, TLSA, TXT,
27};
28use super::record_type::RecordType;
29use crate::error::*;
30use crate::serialize::binary::*;
31
32#[cfg(feature = "dnssec")]
33use super::dnssec::rdata::DNSSECRData;
34
35/// Record data enum variants
36///
37/// [RFC 1035](https://tools.ietf.org/html/rfc1035), DOMAIN NAMES - IMPLEMENTATION AND SPECIFICATION, November 1987
38///
39/// ```text
40/// 3.3. Standard RRs
41///
42/// The following RR definitions are expected to occur, at least
43/// potentially, in all classes.  In particular, NS, SOA, CNAME, and PTR
44/// will be used in all classes, and have the same format in all classes.
45/// Because their RDATA format is known, all domain names in the RDATA
46/// section of these RRs may be compressed.
47///
48/// <domain-name> is a domain name represented as a series of labels, and
49/// terminated by a label with zero length.  <character-string> is a single
50/// length octet followed by that number of characters.  <character-string>
51/// is treated as binary information, and can be up to 256 characters in
52/// length (including the length octet).
53/// ```
54#[cfg_attr(feature = "serde-config", derive(Deserialize, Serialize))]
55#[derive(Debug, EnumAsInner, PartialEq, Clone, Eq)]
56#[non_exhaustive]
57pub enum RData {
58    /// ```text
59    /// -- RFC 1035 -- Domain Implementation and Specification    November 1987
60    ///
61    /// 3.4. Internet specific RRs
62    ///
63    /// 3.4.1. A RDATA format
64    ///
65    ///     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
66    ///     |                    ADDRESS                    |
67    ///     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
68    ///
69    /// where:
70    ///
71    /// ADDRESS         A 32 bit Internet address.
72    ///
73    /// Hosts that have multiple Internet addresses will have multiple A
74    /// records.
75    ///
76    /// A records cause no additional section processing.  The RDATA section of
77    /// an A line in a Zone File is an Internet address expressed as four
78    /// decimal numbers separated by dots without any embedded spaces (e.g.,
79    /// "10.2.0.52" or "192.0.5.6").
80    /// ```
81    A(Ipv4Addr),
82
83    /// ```text
84    /// -- RFC 1886 -- IPv6 DNS Extensions              December 1995
85    ///
86    /// 2.2 AAAA data format
87    ///
88    ///    A 128 bit IPv6 address is encoded in the data portion of an AAAA
89    ///    resource record in network byte order (high-order byte first).
90    /// ```
91    AAAA(Ipv6Addr),
92
93    /// ```text
94    /// 2.  The ANAME resource record
95    ///
96    ///   This document defines the "ANAME" DNS resource record type, with RR
97    ///   TYPE value [TBD].
98    ///
99    /// 2.1.  Presentation and wire format
100    ///
101    ///   The ANAME presentation format is identical to that of CNAME
102    ///   [RFC1033]:
103    ///
104    ///       owner ttl class ANAME target
105    /// ```
106    ANAME(Name),
107
108    /// ```text
109    /// -- RFC 6844          Certification Authority Authorization     January 2013
110    ///
111    /// 5.1.  Syntax
112    ///
113    /// A CAA RR contains a single property entry consisting of a tag-value
114    /// pair.  Each tag represents a property of the CAA record.  The value
115    /// of a CAA property is that specified in the corresponding value field.
116    ///
117    /// A domain name MAY have multiple CAA RRs associated with it and a
118    /// given property MAY be specified more than once.
119    ///
120    /// The CAA data field contains one property entry.  A property entry
121    /// consists of the following data fields:
122    ///
123    /// +0-1-2-3-4-5-6-7-|0-1-2-3-4-5-6-7-|
124    /// | Flags          | Tag Length = n |
125    /// +----------------+----------------+...+---------------+
126    /// | Tag char 0     | Tag char 1     |...| Tag char n-1  |
127    /// +----------------+----------------+...+---------------+
128    /// +----------------+----------------+.....+----------------+
129    /// | Value byte 0   | Value byte 1   |.....| Value byte m-1 |
130    /// +----------------+----------------+.....+----------------+
131
132    /// Where n is the length specified in the Tag length field and m is the
133    /// remaining octets in the Value field (m = d - n - 2) where d is the
134    /// length of the RDATA section.
135    /// ```
136    CAA(CAA),
137
138    /// ```text
139    ///   3.3. Standard RRs
140    ///
141    /// The following RR definitions are expected to occur, at least
142    /// potentially, in all classes.  In particular, NS, SOA, CNAME, and PTR
143    /// will be used in all classes, and have the same format in all classes.
144    /// Because their RDATA format is known, all domain names in the RDATA
145    /// section of these RRs may be compressed.
146    ///
147    /// <domain-name> is a domain name represented as a series of labels, and
148    /// terminated by a label with zero length.  <character-string> is a single
149    /// length octet followed by that number of characters.  <character-string>
150    /// is treated as binary information, and can be up to 256 characters in
151    /// length (including the length octet).
152    ///
153    /// 3.3.1. CNAME RDATA format
154    ///
155    ///     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
156    ///     /                     CNAME                     /
157    ///     /                                               /
158    ///     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
159    ///
160    /// where:
161    ///
162    /// CNAME           A <domain-name> which specifies the canonical or primary
163    ///                 name for the owner.  The owner name is an alias.
164    ///
165    /// CNAME RRs cause no additional section processing, but name servers may
166    /// choose to restart the query at the canonical name in certain cases.  See
167    /// the description of name server logic in [RFC-1034] for details.
168    /// ```
169    CNAME(Name),
170
171    /// ```text
172    /// 2.1.  The CSYNC Resource Record Format
173    ///
174    /// 2.1.1.  The CSYNC Resource Record Wire Format
175    ///
176    /// The CSYNC RDATA consists of the following fields:
177    ///
178    ///                     1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
179    /// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
180    /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
181    /// |                          SOA Serial                           |
182    /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
183    /// |       Flags                   |            Type Bit Map       /
184    /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
185    /// /                     Type Bit Map (continued)                  /
186    /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
187    /// ```
188    CSYNC(CSYNC),
189
190    /// ```text
191    /// 3.3.2. HINFO RDATA format
192    ///
193    ///     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
194    ///     /                      CPU                      /
195    ///     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
196    ///     /                       OS                      /
197    ///     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
198    ///
199    /// where:
200    ///
201    /// CPU             A <character-string> which specifies the CPU type.
202    ///
203    /// OS              A <character-string> which specifies the operating
204    ///                 system type.
205    ///
206    /// Standard values for CPU and OS can be found in [RFC-1010].
207    ///
208    /// HINFO records are used to acquire general information about a host.  The
209    /// main use is for protocols such as FTP that can use special procedures
210    /// when talking between machines or operating systems of the same type.
211    /// ```
212    ///
213    /// `HINFO` is also used by [RFC 8482](https://tools.ietf.org/html/rfc8482)
214    HINFO(HINFO),
215
216    /// [RFC draft-ietf-dnsop-svcb-https-03, DNS SVCB and HTTPS RRs](https://datatracker.ietf.org/doc/html/draft-ietf-dnsop-svcb-https-03#section-8)
217    ///
218    /// ```text
219    ///    8.  Using SVCB with HTTPS and HTTP
220    ///
221    ///    Use of any protocol with SVCB requires a protocol-specific mapping
222    ///    specification.  This section specifies the mapping for HTTPS and
223    ///    HTTP.
224    ///
225    ///    To enable special handling for the HTTPS and HTTP use-cases, the
226    ///    HTTPS RR type is defined as a SVCB-compatible RR type, specific to
227    ///    the https and http schemes.  Clients MUST NOT perform SVCB queries or
228    ///    accept SVCB responses for "https" or "http" schemes.
229    ///
230    ///    The HTTPS RR wire format and presentation format are identical to
231    ///    SVCB, and both share the SvcParamKey registry.  SVCB semantics apply
232    ///    equally to HTTPS RRs unless specified otherwise.  The presentation
233    ///    format of the record is:
234    ///
235    ///    Name TTL IN HTTPS SvcPriority TargetName SvcParams
236    /// ```
237    HTTPS(SVCB),
238
239    /// ```text
240    /// 3.3.9. MX RDATA format
241    ///
242    ///     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
243    ///     |                  PREFERENCE                   |
244    ///     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
245    ///     /                   EXCHANGE                    /
246    ///     /                                               /
247    ///     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
248    ///
249    /// where:
250    ///
251    /// PREFERENCE      A 16 bit integer which specifies the preference given to
252    ///                 this RR among others at the same owner.  Lower values
253    ///                 are preferred.
254    ///
255    /// EXCHANGE        A <domain-name> which specifies a host willing to act as
256    ///                 a mail exchange for the owner name.
257    ///
258    /// MX records cause type A additional section processing for the host
259    /// specified by EXCHANGE.  The use of MX RRs is explained in detail in
260    /// [RFC-974].
261    /// ```
262    MX(MX),
263
264    /// [RFC 3403 DDDS DNS Database, October 2002](https://tools.ietf.org/html/rfc3403#section-4)
265    ///
266    /// ```text
267    /// 4.1 Packet Format
268    ///
269    ///   The packet format of the NAPTR RR is given below.  The DNS type code
270    ///   for NAPTR is 35.
271    ///
272    ///      The packet format for the NAPTR record is as follows
273    ///                                       1  1  1  1  1  1
274    ///         0  1  2  3  4  5  6  7  8  9  0  1  2  3  4  5
275    ///       +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
276    ///       |                     ORDER                     |
277    ///       +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
278    ///       |                   PREFERENCE                  |
279    ///       +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
280    ///       /                     FLAGS                     /
281    ///       +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
282    ///       /                   SERVICES                    /
283    ///       +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
284    ///       /                    REGEXP                     /
285    ///       +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
286    ///       /                  REPLACEMENT                  /
287    ///       /                                               /
288    ///       +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
289    ///
290    ///   <character-string> and <domain-name> as used here are defined in RFC
291    ///   1035 [7].
292    ///
293    ///   ORDER
294    ///      A 16-bit unsigned integer specifying the order in which the NAPTR
295    ///      records MUST be processed in order to accurately represent the
296    ///      ordered list of Rules.  The ordering is from lowest to highest.
297    ///      If two records have the same order value then they are considered
298    ///      to be the same rule and should be selected based on the
299    ///      combination of the Preference values and Services offered.
300    ///
301    ///   PREFERENCE
302    ///      Although it is called "preference" in deference to DNS
303    ///      terminology, this field is equivalent to the Priority value in the
304    ///      DDDS Algorithm.  It is a 16-bit unsigned integer that specifies
305    ///      the order in which NAPTR records with equal Order values SHOULD be
306    ///      processed, low numbers being processed before high numbers.  This
307    ///      is similar to the preference field in an MX record, and is used so
308    ///      domain administrators can direct clients towards more capable
309    ///      hosts or lighter weight protocols.  A client MAY look at records
310    ///      with higher preference values if it has a good reason to do so
311    ///      such as not supporting some protocol or service very well.
312    ///
313    ///      The important difference between Order and Preference is that once
314    ///      a match is found the client MUST NOT consider records with a
315    ///      different Order but they MAY process records with the same Order
316    ///      but different Preferences.  The only exception to this is noted in
317    ///      the second important Note in the DDDS algorithm specification
318    ///      concerning allowing clients to use more complex Service
319    ///      determination between steps 3 and 4 in the algorithm.  Preference
320    ///      is used to give communicate a higher quality of service to rules
321    ///      that are considered the same from an authority standpoint but not
322    ///      from a simple load balancing standpoint.
323    ///
324    ///      It is important to note that DNS contains several load balancing
325    ///      mechanisms and if load balancing among otherwise equal services
326    ///      should be needed then methods such as SRV records or multiple A
327    ///      records should be utilized to accomplish load balancing.
328    ///
329    ///   FLAGS
330    ///      A <character-string> containing flags to control aspects of the
331    ///      rewriting and interpretation of the fields in the record.  Flags
332    ///      are single characters from the set A-Z and 0-9.  The case of the
333    ///      alphabetic characters is not significant.  The field can be empty.
334    ///
335    ///      It is up to the Application specifying how it is using this
336    ///      Database to define the Flags in this field.  It must define which
337    ///      ones are terminal and which ones are not.
338    ///
339    ///   SERVICES
340    ///      A <character-string> that specifies the Service Parameters
341    ///      applicable to this this delegation path.  It is up to the
342    ///      Application Specification to specify the values found in this
343    ///      field.
344    ///
345    ///   REGEXP
346    ///      A <character-string> containing a substitution expression that is
347    ///      applied to the original string held by the client in order to
348    ///      construct the next domain name to lookup.  See the DDDS Algorithm
349    ///      specification for the syntax of this field.
350    ///
351    ///      As stated in the DDDS algorithm, The regular expressions MUST NOT
352    ///      be used in a cumulative fashion, that is, they should only be
353    ///      applied to the original string held by the client, never to the
354    ///      domain name produced by a previous NAPTR rewrite.  The latter is
355    ///      tempting in some applications but experience has shown such use to
356    ///      be extremely fault sensitive, very error prone, and extremely
357    ///      difficult to debug.
358    ///
359    ///   REPLACEMENT
360    ///      A <domain-name> which is the next domain-name to query for
361    ///      depending on the potential values found in the flags field.  This
362    ///      field is used when the regular expression is a simple replacement
363    ///      operation.  Any value in this field MUST be a fully qualified
364    ///      domain-name.  Name compression is not to be used for this field.
365    ///
366    ///      This field and the REGEXP field together make up the Substitution
367    ///      Expression in the DDDS Algorithm.  It is simply a historical
368    ///      optimization specifically for DNS compression that this field
369    ///      exists.  The fields are also mutually exclusive.  If a record is
370    ///      returned that has values for both fields then it is considered to
371    ///      be in error and SHOULD be either ignored or an error returned.
372    /// ```
373    NAPTR(NAPTR),
374
375    /// ```text
376    /// 3.3.10. NULL RDATA format (EXPERIMENTAL)
377    ///
378    ///     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
379    ///     /                  <anything>                   /
380    ///     /                                               /
381    ///     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
382    ///
383    /// Anything at all may be in the RDATA field so long as it is 65535 octets
384    /// or less.
385    ///
386    /// NULL records cause no additional section processing.  NULL RRs are not
387    /// allowed in Zone Files.  NULLs are used as placeholders in some
388    /// experimental extensions of the DNS.
389    /// ```
390    NULL(NULL),
391
392    /// ```text
393    /// 3.3.11. NS RDATA format
394    ///
395    ///     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
396    ///     /                   NSDNAME                     /
397    ///     /                                               /
398    ///     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
399    ///
400    /// where:
401    ///
402    /// NSDNAME         A <domain-name> which specifies a host which should be
403    ///                 authoritative for the specified class and domain.
404    ///
405    /// NS records cause both the usual additional section processing to locate
406    /// a type A record, and, when used in a referral, a special search of the
407    /// zone in which they reside for glue information.
408    ///
409    /// The NS RR states that the named host should be expected to have a zone
410    /// starting at owner name of the specified class.  Note that the class may
411    /// not indicate the protocol family which should be used to communicate
412    /// with the host, although it is typically a strong hint.  For example,
413    /// hosts which are name servers for either Internet (IN) or Hesiod (HS)
414    /// class information are normally queried using IN class protocols.
415    /// ```
416    NS(Name),
417
418    /// [RFC 7929](https://tools.ietf.org/html/rfc7929#section-2.1)
419    ///
420    /// ```text
421    /// The RDATA portion of an OPENPGPKEY resource record contains a single
422    /// value consisting of a Transferable Public Key formatted as specified
423    /// in [RFC4880].
424    /// ```
425    OPENPGPKEY(OPENPGPKEY),
426
427    /// ```text
428    /// RFC 6891                   EDNS(0) Extensions                 April 2013
429    /// 6.1.2.  Wire Format
430    ///
431    ///        +------------+--------------+------------------------------+
432    ///        | Field Name | Field Type   | Description                  |
433    ///        +------------+--------------+------------------------------+
434    ///        | NAME       | domain name  | MUST be 0 (root domain)      |
435    ///        | TYPE       | u_int16_t    | OPT (41)                     |
436    ///        | CLASS      | u_int16_t    | requestor's UDP payload size |
437    ///        | TTL        | u_int32_t    | extended RCODE and flags     |
438    ///        | RDLEN      | u_int16_t    | length of all RDATA          |
439    ///        | RDATA      | octet stream | {attribute,value} pairs      |
440    ///        +------------+--------------+------------------------------+
441    ///
442    /// The variable part of an OPT RR may contain zero or more options in
443    ///    the RDATA.  Each option MUST be treated as a bit field.  Each option
444    ///    is encoded as:
445    ///
446    ///                   +0 (MSB)                            +1 (LSB)
447    ///        +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
448    ///     0: |                          OPTION-CODE                          |
449    ///        +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
450    ///     2: |                         OPTION-LENGTH                         |
451    ///        +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
452    ///     4: |                                                               |
453    ///        /                          OPTION-DATA                          /
454    ///        /                                                               /
455    ///        +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
456    /// ```
457    OPT(OPT),
458
459    /// ```text
460    /// 3.3.12. PTR RDATA format
461    ///
462    ///     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
463    ///     /                   PTRDNAME                    /
464    ///     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
465    ///
466    /// where:
467    ///
468    /// PTRDNAME        A <domain-name> which points to some location in the
469    ///                 domain name space.
470    ///
471    /// PTR records cause no additional section processing.  These RRs are used
472    /// in special domains to point to some other location in the domain space.
473    /// These records are simple data, and don't imply any special processing
474    /// similar to that performed by CNAME, which identifies aliases.  See the
475    /// description of the IN-ADDR.ARPA domain for an example.
476    /// ```
477    PTR(Name),
478
479    /// ```text
480    /// 3.3.13. SOA RDATA format
481    ///
482    ///     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
483    ///     /                     MNAME                     /
484    ///     /                                               /
485    ///     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
486    ///     /                     RNAME                     /
487    ///     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
488    ///     |                    SERIAL                     |
489    ///     |                                               |
490    ///     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
491    ///     |                    REFRESH                    |
492    ///     |                                               |
493    ///     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
494    ///     |                     RETRY                     |
495    ///     |                                               |
496    ///     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
497    ///     |                    EXPIRE                     |
498    ///     |                                               |
499    ///     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
500    ///     |                    MINIMUM                    |
501    ///     |                                               |
502    ///     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
503    ///
504    /// where:
505    ///
506    /// MNAME           The <domain-name> of the name server that was the
507    ///                 original or primary source of data for this zone.
508    ///
509    /// RNAME           A <domain-name> which specifies the mailbox of the
510    ///                 person responsible for this zone.
511    ///
512    /// SERIAL          The unsigned 32 bit version number of the original copy
513    ///                 of the zone.  Zone transfers preserve this value.  This
514    ///                 value wraps and should be compared using sequence space
515    ///                 arithmetic.
516    ///
517    /// REFRESH         A 32 bit time interval before the zone should be
518    ///                 refreshed.
519    ///
520    /// RETRY           A 32 bit time interval that should elapse before a
521    ///                 failed refresh should be retried.
522    ///
523    /// EXPIRE          A 32 bit time value that specifies the upper limit on
524    ///                 the time interval that can elapse before the zone is no
525    ///                 longer authoritative.
526    ///
527    /// MINIMUM         The unsigned 32 bit minimum TTL field that should be
528    ///                 exported with any RR from this zone.
529    ///
530    /// SOA records cause no additional section processing.
531    ///
532    /// All times are in units of seconds.
533    ///
534    /// Most of these fields are pertinent only for name server maintenance
535    /// operations.  However, MINIMUM is used in all query operations that
536    /// retrieve RRs from a zone.  Whenever a RR is sent in a response to a
537    /// query, the TTL field is set to the maximum of the TTL field from the RR
538    /// and the MINIMUM field in the appropriate SOA.  Thus MINIMUM is a lower
539    /// bound on the TTL field for all RRs in a zone.  Note that this use of
540    /// MINIMUM should occur when the RRs are copied into the response and not
541    /// when the zone is loaded from a Zone File or via a zone transfer.  The
542    /// reason for this provision is to allow future dynamic update facilities to
543    /// change the SOA RR with known semantics.
544    /// ```
545    SOA(SOA),
546
547    /// ```text
548    /// RFC 2782                       DNS SRV RR                  February 2000
549    ///
550    /// The format of the SRV RR
551    ///
552    ///  _Service._Proto.Name TTL Class SRV Priority Weight Port Target
553    /// ```
554    SRV(SRV),
555
556    /// [RFC 4255](https://tools.ietf.org/html/rfc4255#section-3.1)
557    ///
558    /// ```text
559    /// 3.1.  The SSHFP RDATA Format
560    ///
561    ///    The RDATA for a SSHFP RR consists of an algorithm number, fingerprint
562    ///    type and the fingerprint of the public host key.
563    ///
564    ///        1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
565    ///        0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
566    ///        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
567    ///        |   algorithm   |    fp type    |                               /
568    ///        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+                               /
569    ///        /                                                               /
570    ///        /                          fingerprint                          /
571    ///        /                                                               /
572    ///        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
573    ///
574    /// 3.1.1.  Algorithm Number Specification
575    ///
576    ///    This algorithm number octet describes the algorithm of the public
577    ///    key.  The following values are assigned:
578    ///
579    ///           Value    Algorithm name
580    ///           -----    --------------
581    ///           0        reserved
582    ///           1        RSA
583    ///           2        DSS
584    ///
585    ///    Reserving other types requires IETF consensus [4].
586    ///
587    /// 3.1.2.  Fingerprint Type Specification
588    ///
589    ///    The fingerprint type octet describes the message-digest algorithm
590    ///    used to calculate the fingerprint of the public key.  The following
591    ///    values are assigned:
592    ///
593    ///           Value    Fingerprint type
594    ///           -----    ----------------
595    ///           0        reserved
596    ///           1        SHA-1
597    ///
598    ///    Reserving other types requires IETF consensus [4].
599    ///
600    ///    For interoperability reasons, as few fingerprint types as possible
601    ///    should be reserved.  The only reason to reserve additional types is
602    ///    to increase security.
603    ///
604    /// 3.1.3.  Fingerprint
605    ///
606    ///    The fingerprint is calculated over the public key blob as described
607    ///    in [7].
608    ///
609    ///    The message-digest algorithm is presumed to produce an opaque octet
610    ///    string output, which is placed as-is in the RDATA fingerprint field.
611    /// ```
612    ///
613    /// The algorithm and fingerprint type values have been updated in
614    /// [RFC 6594](https://tools.ietf.org/html/rfc6594) and
615    /// [RFC 7479](https://tools.ietf.org/html/rfc7479).
616    SSHFP(SSHFP),
617
618    /// [RFC draft-ietf-dnsop-svcb-https-03, DNS SVCB and HTTPS RRs](https://datatracker.ietf.org/doc/html/draft-ietf-dnsop-svcb-https-03#section-2)
619    ///
620    /// ```text
621    ///    2.  The SVCB record type
622    ///
623    ///   The SVCB DNS resource record (RR) type (RR type 64) is used to locate
624    ///   alternative endpoints for a service.
625    ///
626    ///   The algorithm for resolving SVCB records and associated address
627    ///   records is specified in Section 3.
628    ///
629    ///   Other SVCB-compatible resource record types can also be defined as-
630    ///   needed.  In particular, the HTTPS RR (RR type 65) provides special
631    ///   handling for the case of "https" origins as described in Section 8.
632    ///
633    ///   SVCB RRs are extensible by a list of SvcParams, which are pairs
634    ///   consisting of a SvcParamKey and a SvcParamValue.  Each SvcParamKey
635    ///   has a presentation name and a registered number.  Values are in a
636    ///   format specific to the SvcParamKey.  Their definition should specify
637    ///   both their presentation format and wire encoding (e.g., domain names,
638    ///   binary data, or numeric values).  The initial SvcParamKeys and
639    ///   formats are defined in Section 6.
640    /// ```
641    SVCB(SVCB),
642
643    /// [RFC 6698, DNS-Based Authentication for TLS](https://tools.ietf.org/html/rfc6698#section-2.1)
644    ///
645    /// ```text
646    ///                         1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
647    ///     0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
648    ///    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
649    ///    |  Cert. Usage  |   Selector    | Matching Type |               /
650    ///    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+               /
651    ///    /                                                               /
652    ///    /                 Certificate Association Data                  /
653    ///    /                                                               /
654    ///    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
655    /// ```
656    TLSA(TLSA),
657
658    /// ```text
659    /// 3.3.14. TXT RDATA format
660    ///
661    ///     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
662    ///     /                   TXT-DATA                    /
663    ///     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
664    ///
665    /// where:
666    ///
667    /// TXT-DATA        One or more <character-string>s.
668    ///
669    /// TXT RRs are used to hold descriptive text.  The semantics of the text
670    /// depends on the domain where it is found.
671    /// ```
672    TXT(TXT),
673
674    /// A DNSSEC- or SIG(0)- specific record. See `DNSSECRData` for details.
675    ///
676    /// These types are in `DNSSECRData` to make them easy to disable when
677    /// crypto functionality isn't needed.
678    #[cfg(feature = "dnssec")]
679    #[cfg_attr(docsrs, doc(cfg(feature = "dnssec")))]
680    DNSSEC(DNSSECRData),
681
682    /// Unknown RecordData is for record types not supported by Trust-DNS
683    Unknown {
684        /// RecordType code
685        code: u16,
686        /// RData associated to the record
687        rdata: NULL,
688    },
689
690    /// This corresponds to a record type of 0, unspecified
691    #[deprecated(note = "Use None for the RData in the resource record instead")]
692    ZERO,
693}
694
695impl RData {
696    fn to_bytes(&self) -> Vec<u8> {
697        let mut buf: Vec<u8> = Vec::new();
698        {
699            let mut encoder: BinEncoder<'_> = BinEncoder::new(&mut buf);
700            self.emit(&mut encoder).unwrap_or_else(|_| {
701                warn!("could not encode RDATA: {:?}", self);
702            });
703        }
704        buf
705    }
706
707    /// Read the RData from the given Decoder
708    pub fn read(
709        decoder: &mut BinDecoder<'_>,
710        record_type: RecordType,
711        rdata_length: Restrict<u16>,
712    ) -> ProtoResult<Self> {
713        let start_idx = decoder.index();
714
715        let result = match record_type {
716            RecordType::A => {
717                trace!("reading A");
718                rdata::a::read(decoder).map(Self::A)
719            }
720            RecordType::AAAA => {
721                trace!("reading AAAA");
722                rdata::aaaa::read(decoder).map(Self::AAAA)
723            }
724            RecordType::ANAME => {
725                trace!("reading ANAME");
726                rdata::name::read(decoder).map(Self::ANAME)
727            }
728            rt @ RecordType::ANY | rt @ RecordType::AXFR | rt @ RecordType::IXFR => {
729                return Err(ProtoErrorKind::UnknownRecordTypeValue(rt.into()).into());
730            }
731            RecordType::CAA => {
732                trace!("reading CAA");
733                rdata::caa::read(decoder, rdata_length).map(Self::CAA)
734            }
735            RecordType::CNAME => {
736                trace!("reading CNAME");
737                rdata::name::read(decoder).map(Self::CNAME)
738            }
739            RecordType::CSYNC => {
740                trace!("reading CSYNC");
741                rdata::csync::read(decoder, rdata_length).map(Self::CSYNC)
742            }
743            RecordType::HINFO => {
744                trace!("reading HINFO");
745                rdata::hinfo::read(decoder).map(Self::HINFO)
746            }
747            RecordType::HTTPS => {
748                trace!("reading HTTPS");
749                rdata::svcb::read(decoder, rdata_length).map(Self::HTTPS)
750            }
751            RecordType::ZERO => {
752                trace!("reading EMPTY");
753                // we should never get here, since ZERO should be 0 length, and None in the Record.
754                //   this invariant is verified below, and the decoding will fail with an err.
755                #[allow(deprecated)]
756                Ok(Self::ZERO)
757            }
758            RecordType::MX => {
759                trace!("reading MX");
760                rdata::mx::read(decoder).map(Self::MX)
761            }
762            RecordType::NAPTR => {
763                trace!("reading NAPTR");
764                rdata::naptr::read(decoder).map(Self::NAPTR)
765            }
766            RecordType::NULL => {
767                trace!("reading NULL");
768                rdata::null::read(decoder, rdata_length).map(Self::NULL)
769            }
770            RecordType::NS => {
771                trace!("reading NS");
772                rdata::name::read(decoder).map(Self::NS)
773            }
774            RecordType::OPENPGPKEY => {
775                trace!("reading OPENPGPKEY");
776                rdata::openpgpkey::read(decoder, rdata_length).map(Self::OPENPGPKEY)
777            }
778            RecordType::OPT => {
779                trace!("reading OPT");
780                rdata::opt::read(decoder, rdata_length).map(Self::OPT)
781            }
782            RecordType::PTR => {
783                trace!("reading PTR");
784                rdata::name::read(decoder).map(Self::PTR)
785            }
786            RecordType::SOA => {
787                trace!("reading SOA");
788                rdata::soa::read(decoder).map(Self::SOA)
789            }
790            RecordType::SRV => {
791                trace!("reading SRV");
792                rdata::srv::read(decoder).map(Self::SRV)
793            }
794            RecordType::SSHFP => {
795                trace!("reading SSHFP");
796                rdata::sshfp::read(decoder, rdata_length).map(Self::SSHFP)
797            }
798            RecordType::SVCB => {
799                trace!("reading SVCB");
800                rdata::svcb::read(decoder, rdata_length).map(Self::SVCB)
801            }
802            RecordType::TLSA => {
803                trace!("reading TLSA");
804                rdata::tlsa::read(decoder, rdata_length).map(Self::TLSA)
805            }
806            RecordType::TXT => {
807                trace!("reading TXT");
808                rdata::txt::read(decoder, rdata_length).map(Self::TXT)
809            }
810            #[cfg(feature = "dnssec")]
811            r if r.is_dnssec() => {
812                DNSSECRData::read(decoder, record_type, rdata_length).map(Self::DNSSEC)
813            }
814            record_type => {
815                trace!("reading Unknown record: {}", record_type);
816                rdata::null::read(decoder, rdata_length).map(|rdata| Self::Unknown {
817                    code: record_type.into(),
818                    rdata,
819                })
820            }
821        };
822
823        // we should have read rdata_length, but we did not
824        let read = decoder.index() - start_idx;
825        rdata_length
826            .map(|u| u as usize)
827            .verify_unwrap(|rdata_length| read == *rdata_length)
828            .map_err(|rdata_length| {
829                ProtoError::from(ProtoErrorKind::IncorrectRDataLengthRead {
830                    read,
831                    len: rdata_length,
832                })
833            })?;
834
835        result
836    }
837
838    /// [RFC 4034](https://tools.ietf.org/html/rfc4034#section-6), DNSSEC Resource Records, March 2005
839    ///
840    /// ```text
841    /// 6.2.  Canonical RR Form
842    ///
843    ///    For the purposes of DNS security, the canonical form of an RR is the
844    ///    wire format of the RR where:
845    ///
846    ///    ...
847    ///
848    ///    3.  if the type of the RR is NS, MD, MF, CNAME, SOA, MB, MG, MR, PTR,
849    ///        HINFO, MINFO, MX, HINFO, RP, AFSDB, RT, SIG, PX, NXT, NAPTR, KX,
850    ///        SRV, DNAME, A6, RRSIG, or (rfc6840 removes NSEC), all uppercase
851    ///        US-ASCII letters in the DNS names contained within the RDATA are replaced
852    ///        by the corresponding lowercase US-ASCII letters;
853    /// ```
854    ///
855    /// Canonical name form for all non-1035 records:
856    ///   [RFC 3579](https://tools.ietf.org/html/rfc3597)
857    /// ```text
858    ///  4.  Domain Name Compression
859    ///
860    ///   RRs containing compression pointers in the RDATA part cannot be
861    ///   treated transparently, as the compression pointers are only
862    ///   meaningful within the context of a DNS message.  Transparently
863    ///   copying the RDATA into a new DNS message would cause the compression
864    ///   pointers to point at the corresponding location in the new message,
865    ///   which now contains unrelated data.  This would cause the compressed
866    ///   name to be corrupted.
867    ///
868    ///   To avoid such corruption, servers MUST NOT compress domain names
869    ///   embedded in the RDATA of types that are class-specific or not well-
870    ///   known.  This requirement was stated in [RFC1123] without defining the
871    ///   term "well-known"; it is hereby specified that only the RR types
872    ///   defined in [RFC1035] are to be considered "well-known".
873    ///
874    ///   The specifications of a few existing RR types have explicitly allowed
875    ///   compression contrary to this specification: [RFC2163] specified that
876    ///   compression applies to the PX RR, and [RFC2535] allowed compression
877    ///   in SIG RRs and NXT RRs records.  Since this specification disallows
878    ///   compression in these cases, it is an update to [RFC2163] (section 4)
879    ///   and [RFC2535] (sections 4.1.7 and 5.2).
880    ///
881    ///   Receiving servers MUST decompress domain names in RRs of well-known
882    ///   type, and SHOULD also decompress RRs of type RP, AFSDB, RT, SIG, PX,
883    ///   NXT, NAPTR, and SRV (although the current specification of the SRV RR
884    ///   in [RFC2782] prohibits compression, [RFC2052] mandated it, and some
885    ///   servers following that earlier specification are still in use).
886    ///
887    ///   Future specifications for new RR types that contain domain names
888    ///   within their RDATA MUST NOT allow the use of name compression for
889    ///   those names, and SHOULD explicitly state that the embedded domain
890    ///   names MUST NOT be compressed.
891    ///
892    ///   As noted in [RFC1123], the owner name of an RR is always eligible for
893    ///   compression.
894    ///
895    ///   ...
896    ///   As a courtesy to implementors, it is hereby noted that the complete
897    ///    set of such previously published RR types that contain embedded
898    ///    domain names, and whose DNSSEC canonical form therefore involves
899    ///   downcasing according to the DNS rules for character comparisons,
900    ///   consists of the RR types NS, MD, MF, CNAME, SOA, MB, MG, MR, PTR,
901    ///   HINFO, MINFO, MX, HINFO, RP, AFSDB, RT, SIG, PX, NXT, NAPTR, KX, SRV,
902    ///   DNAME, and A6.
903    ///   ...
904    /// ```
905    pub fn emit(&self, encoder: &mut BinEncoder<'_>) -> ProtoResult<()> {
906        match *self {
907            Self::A(address) => rdata::a::emit(encoder, address),
908            Self::AAAA(ref address) => rdata::aaaa::emit(encoder, address),
909            Self::ANAME(ref name) => {
910                encoder.with_canonical_names(|encoder| rdata::name::emit(encoder, name))
911            }
912            Self::CAA(ref caa) => {
913                encoder.with_canonical_names(|encoder| rdata::caa::emit(encoder, caa))
914            }
915            // to_lowercase for rfc4034 and rfc6840
916            Self::CNAME(ref name) | RData::NS(ref name) | RData::PTR(ref name) => {
917                rdata::name::emit(encoder, name)
918            }
919            Self::CSYNC(ref csync) => rdata::csync::emit(encoder, csync),
920            Self::HINFO(ref hinfo) => rdata::hinfo::emit(encoder, hinfo),
921            Self::HTTPS(ref svcb) => rdata::svcb::emit(encoder, svcb),
922            Self::ZERO => Ok(()),
923            // to_lowercase for rfc4034 and rfc6840
924            Self::MX(ref mx) => rdata::mx::emit(encoder, mx),
925            Self::NAPTR(ref naptr) => {
926                encoder.with_canonical_names(|encoder| rdata::naptr::emit(encoder, naptr))
927            }
928            Self::NULL(ref null) => rdata::null::emit(encoder, null),
929            Self::OPENPGPKEY(ref openpgpkey) => {
930                encoder.with_canonical_names(|encoder| rdata::openpgpkey::emit(encoder, openpgpkey))
931            }
932            Self::OPT(ref opt) => rdata::opt::emit(encoder, opt),
933            // to_lowercase for rfc4034 and rfc6840
934            Self::SOA(ref soa) => rdata::soa::emit(encoder, soa),
935            // to_lowercase for rfc4034 and rfc6840
936            Self::SRV(ref srv) => {
937                encoder.with_canonical_names(|encoder| rdata::srv::emit(encoder, srv))
938            }
939            Self::SSHFP(ref sshfp) => {
940                encoder.with_canonical_names(|encoder| rdata::sshfp::emit(encoder, sshfp))
941            }
942            Self::SVCB(ref svcb) => rdata::svcb::emit(encoder, svcb),
943            Self::TLSA(ref tlsa) => {
944                encoder.with_canonical_names(|encoder| rdata::tlsa::emit(encoder, tlsa))
945            }
946            Self::TXT(ref txt) => rdata::txt::emit(encoder, txt),
947            #[cfg(feature = "dnssec")]
948            Self::DNSSEC(ref rdata) => encoder.with_canonical_names(|encoder| rdata.emit(encoder)),
949            Self::Unknown { ref rdata, .. } => rdata::null::emit(encoder, rdata),
950        }
951    }
952
953    /// Converts this to a Recordtype
954    pub fn to_record_type(&self) -> RecordType {
955        match *self {
956            Self::A(..) => RecordType::A,
957            Self::AAAA(..) => RecordType::AAAA,
958            Self::ANAME(..) => RecordType::ANAME,
959            Self::CAA(..) => RecordType::CAA,
960            Self::CNAME(..) => RecordType::CNAME,
961            Self::CSYNC(..) => RecordType::CSYNC,
962            Self::HINFO(..) => RecordType::HINFO,
963            Self::HTTPS(..) => RecordType::HTTPS,
964            Self::MX(..) => RecordType::MX,
965            Self::NAPTR(..) => RecordType::NAPTR,
966            Self::NS(..) => RecordType::NS,
967            Self::NULL(..) => RecordType::NULL,
968            Self::OPENPGPKEY(..) => RecordType::OPENPGPKEY,
969            Self::OPT(..) => RecordType::OPT,
970            Self::PTR(..) => RecordType::PTR,
971            Self::SOA(..) => RecordType::SOA,
972            Self::SRV(..) => RecordType::SRV,
973            Self::SSHFP(..) => RecordType::SSHFP,
974            Self::SVCB(..) => RecordType::SVCB,
975            Self::TLSA(..) => RecordType::TLSA,
976            Self::TXT(..) => RecordType::TXT,
977            #[cfg(feature = "dnssec")]
978            Self::DNSSEC(ref rdata) => DNSSECRData::to_record_type(rdata),
979            Self::Unknown { code, .. } => RecordType::Unknown(code),
980            Self::ZERO => RecordType::ZERO,
981        }
982    }
983
984    /// If this is an A or AAAA record type, then an IpAddr will be returned
985    pub fn to_ip_addr(&self) -> Option<IpAddr> {
986        match *self {
987            Self::A(a) => Some(IpAddr::from(a)),
988            Self::AAAA(aaaa) => Some(IpAddr::from(aaaa)),
989            _ => None,
990        }
991    }
992
993    /// Returns true if
994    pub fn is_soa(&self) -> bool {
995        matches!(self, RData::SOA(..))
996    }
997}
998
999impl fmt::Display for RData {
1000    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
1001        fn w<D: fmt::Display>(f: &mut fmt::Formatter<'_>, d: D) -> Result<(), fmt::Error> {
1002            write!(f, "{rdata}", rdata = d)
1003        }
1004
1005        match *self {
1006            Self::A(address) => w(f, address),
1007            Self::AAAA(ref address) => w(f, address),
1008            Self::ANAME(ref name) => w(f, name),
1009            Self::CAA(ref caa) => w(f, caa),
1010            // to_lowercase for rfc4034 and rfc6840
1011            Self::CNAME(ref name) | RData::NS(ref name) | RData::PTR(ref name) => w(f, name),
1012            Self::CSYNC(ref csync) => w(f, csync),
1013            Self::HINFO(ref hinfo) => w(f, hinfo),
1014            Self::HTTPS(ref svcb) => w(f, svcb),
1015            Self::ZERO => Ok(()),
1016            // to_lowercase for rfc4034 and rfc6840
1017            Self::MX(ref mx) => w(f, mx),
1018            Self::NAPTR(ref naptr) => w(f, naptr),
1019            Self::NULL(ref null) => w(f, null),
1020            Self::OPENPGPKEY(ref openpgpkey) => w(f, openpgpkey),
1021            // Opt has no display representation
1022            Self::OPT(_) => Err(fmt::Error),
1023            // to_lowercase for rfc4034 and rfc6840
1024            Self::SOA(ref soa) => w(f, soa),
1025            // to_lowercase for rfc4034 and rfc6840
1026            Self::SRV(ref srv) => w(f, srv),
1027            Self::SSHFP(ref sshfp) => w(f, sshfp),
1028            Self::SVCB(ref svcb) => w(f, svcb),
1029            Self::TLSA(ref tlsa) => w(f, tlsa),
1030            Self::TXT(ref txt) => w(f, txt),
1031            #[cfg(feature = "dnssec")]
1032            Self::DNSSEC(ref rdata) => w(f, rdata),
1033            Self::Unknown { ref rdata, .. } => w(f, rdata),
1034        }
1035    }
1036}
1037
1038impl PartialOrd<Self> for RData {
1039    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
1040        Some(self.cmp(other))
1041    }
1042}
1043
1044impl Ord for RData {
1045    // RFC 4034                DNSSEC Resource Records               March 2005
1046    //
1047    // 6.3.  Canonical RR Ordering within an RRset
1048    //
1049    //    For the purposes of DNS security, RRs with the same owner name,
1050    //    class, and type are sorted by treating the RDATA portion of the
1051    //    canonical form of each RR as a left-justified unsigned octet sequence
1052    //    in which the absence of an octet sorts before a zero octet.
1053    //
1054    //    [RFC2181] specifies that an RRset is not allowed to contain duplicate
1055    //    records (multiple RRs with the same owner name, class, type, and
1056    //    RDATA).  Therefore, if an implementation detects duplicate RRs when
1057    //    putting the RRset in canonical form, it MUST treat this as a protocol
1058    //    error.  If the implementation chooses to handle this protocol error
1059    //    in the spirit of the robustness principle (being liberal in what it
1060    //    accepts), it MUST remove all but one of the duplicate RR(s) for the
1061    //    purposes of calculating the canonical form of the RRset.
1062    fn cmp(&self, other: &Self) -> Ordering {
1063        // TODO: how about we just store the bytes with the decoded data?
1064        //  the decoded data is useful for queries, the encoded data is needed for transfers, signing
1065        //  and ordering.
1066        self.to_bytes().cmp(&other.to_bytes())
1067    }
1068}
1069
1070#[cfg(test)]
1071mod tests {
1072    #![allow(clippy::dbg_macro, clippy::print_stdout)]
1073
1074    use std::net::Ipv4Addr;
1075    use std::net::Ipv6Addr;
1076    use std::str::FromStr;
1077
1078    use super::*;
1079    use crate::rr::domain::Name;
1080    use crate::rr::rdata::{MX, SOA, SRV, TXT};
1081    use crate::serialize::binary::bin_tests::test_emit_data_set;
1082    #[allow(clippy::useless_attribute)]
1083    #[allow(unused)]
1084    use crate::serialize::binary::*;
1085
1086    fn get_data() -> Vec<(RData, Vec<u8>)> {
1087        vec![
1088            (
1089                RData::CNAME(Name::from_str("www.example.com").unwrap()),
1090                vec![
1091                    3, b'w', b'w', b'w', 7, b'e', b'x', b'a', b'm', b'p', b'l', b'e', 3, b'c',
1092                    b'o', b'm', 0,
1093                ],
1094            ),
1095            (
1096                RData::MX(MX::new(256, Name::from_str("n").unwrap())),
1097                vec![1, 0, 1, b'n', 0],
1098            ),
1099            (
1100                RData::NS(Name::from_str("www.example.com").unwrap()),
1101                vec![
1102                    3, b'w', b'w', b'w', 7, b'e', b'x', b'a', b'm', b'p', b'l', b'e', 3, b'c',
1103                    b'o', b'm', 0,
1104                ],
1105            ),
1106            (
1107                RData::PTR(Name::from_str("www.example.com").unwrap()),
1108                vec![
1109                    3, b'w', b'w', b'w', 7, b'e', b'x', b'a', b'm', b'p', b'l', b'e', 3, b'c',
1110                    b'o', b'm', 0,
1111                ],
1112            ),
1113            (
1114                RData::SOA(SOA::new(
1115                    Name::from_str("www.example.com").unwrap(),
1116                    Name::from_str("xxx.example.com").unwrap(),
1117                    u32::max_value(),
1118                    -1,
1119                    -1,
1120                    -1,
1121                    u32::max_value(),
1122                )),
1123                vec![
1124                    3, b'w', b'w', b'w', 7, b'e', b'x', b'a', b'm', b'p', b'l', b'e', 3, b'c',
1125                    b'o', b'm', 0, 3, b'x', b'x', b'x', 0xC0, 0x04, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
1126                    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
1127                    0xFF, 0xFF,
1128                ],
1129            ),
1130            (
1131                RData::TXT(TXT::new(vec![
1132                    "abcdef".to_string(),
1133                    "ghi".to_string(),
1134                    "".to_string(),
1135                    "j".to_string(),
1136                ])),
1137                vec![
1138                    6, b'a', b'b', b'c', b'd', b'e', b'f', 3, b'g', b'h', b'i', 0, 1, b'j',
1139                ],
1140            ),
1141            (
1142                RData::A(Ipv4Addr::from_str("0.0.0.0").unwrap()),
1143                vec![0, 0, 0, 0],
1144            ),
1145            (
1146                RData::AAAA(Ipv6Addr::from_str("::").unwrap()),
1147                vec![0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
1148            ),
1149            (
1150                RData::SRV(SRV::new(
1151                    1,
1152                    2,
1153                    3,
1154                    Name::from_str("www.example.com").unwrap(),
1155                )),
1156                vec![
1157                    0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 3, b'w', b'w', b'w', 7, b'e', b'x', b'a',
1158                    b'm', b'p', b'l', b'e', 3, b'c', b'o', b'm', 0,
1159                ],
1160            ),
1161            (
1162                RData::HINFO(HINFO::new("cpu".to_string(), "os".to_string())),
1163                vec![3, b'c', b'p', b'u', 2, b'o', b's'],
1164            ),
1165        ]
1166    }
1167
1168    // TODO this test kinda sucks, shows the problem with not storing the binary parts
1169    #[test]
1170    fn test_order() {
1171        let ordered: Vec<RData> = vec![
1172            RData::A(Ipv4Addr::from_str("0.0.0.0").unwrap()),
1173            RData::AAAA(Ipv6Addr::from_str("::").unwrap()),
1174            RData::SRV(SRV::new(
1175                1,
1176                2,
1177                3,
1178                Name::from_str("www.example.com").unwrap(),
1179            )),
1180            RData::MX(MX::new(256, Name::from_str("n").unwrap())),
1181            RData::CNAME(Name::from_str("www.example.com").unwrap()),
1182            RData::PTR(Name::from_str("www.example.com").unwrap()),
1183            RData::NS(Name::from_str("www.example.com").unwrap()),
1184            RData::SOA(SOA::new(
1185                Name::from_str("www.example.com").unwrap(),
1186                Name::from_str("xxx.example.com").unwrap(),
1187                u32::max_value(),
1188                -1,
1189                -1,
1190                -1,
1191                u32::max_value(),
1192            )),
1193            RData::TXT(TXT::new(vec![
1194                "abcdef".to_string(),
1195                "ghi".to_string(),
1196                "".to_string(),
1197                "j".to_string(),
1198            ])),
1199        ];
1200        let mut unordered = vec![
1201            RData::CNAME(Name::from_str("www.example.com").unwrap()),
1202            RData::MX(MX::new(256, Name::from_str("n").unwrap())),
1203            RData::PTR(Name::from_str("www.example.com").unwrap()),
1204            RData::NS(Name::from_str("www.example.com").unwrap()),
1205            RData::SOA(SOA::new(
1206                Name::from_str("www.example.com").unwrap(),
1207                Name::from_str("xxx.example.com").unwrap(),
1208                u32::max_value(),
1209                -1,
1210                -1,
1211                -1,
1212                u32::max_value(),
1213            )),
1214            RData::TXT(TXT::new(vec![
1215                "abcdef".to_string(),
1216                "ghi".to_string(),
1217                "".to_string(),
1218                "j".to_string(),
1219            ])),
1220            RData::A(Ipv4Addr::from_str("0.0.0.0").unwrap()),
1221            RData::AAAA(Ipv6Addr::from_str("::").unwrap()),
1222            RData::SRV(SRV::new(
1223                1,
1224                2,
1225                3,
1226                Name::from_str("www.example.com").unwrap(),
1227            )),
1228        ];
1229
1230        unordered.sort();
1231        assert_eq!(ordered, unordered);
1232    }
1233
1234    #[test]
1235    fn test_read() {
1236        for (test_pass, (expect, binary)) in get_data().into_iter().enumerate() {
1237            println!("test {}: {:?}", test_pass, binary);
1238            let length = binary.len() as u16; // pre exclusive borrow
1239            let mut decoder = BinDecoder::new(&binary);
1240
1241            assert_eq!(
1242                RData::read(
1243                    &mut decoder,
1244                    record_type_from_rdata(&expect),
1245                    Restrict::new(length)
1246                )
1247                .unwrap(),
1248                expect
1249            );
1250        }
1251    }
1252
1253    fn record_type_from_rdata(rdata: &RData) -> crate::rr::record_type::RecordType {
1254        match *rdata {
1255            RData::A(..) => RecordType::A,
1256            RData::AAAA(..) => RecordType::AAAA,
1257            RData::ANAME(..) => RecordType::ANAME,
1258            RData::CAA(..) => RecordType::CAA,
1259            RData::CNAME(..) => RecordType::CNAME,
1260            RData::CSYNC(..) => RecordType::CSYNC,
1261            RData::HINFO(..) => RecordType::HINFO,
1262            RData::HTTPS(..) => RecordType::HTTPS,
1263            RData::MX(..) => RecordType::MX,
1264            RData::NAPTR(..) => RecordType::NAPTR,
1265            RData::NS(..) => RecordType::NS,
1266            RData::NULL(..) => RecordType::NULL,
1267            RData::OPENPGPKEY(..) => RecordType::OPENPGPKEY,
1268            RData::OPT(..) => RecordType::OPT,
1269            RData::PTR(..) => RecordType::PTR,
1270            RData::SOA(..) => RecordType::SOA,
1271            RData::SRV(..) => RecordType::SRV,
1272            RData::SSHFP(..) => RecordType::SSHFP,
1273            RData::SVCB(..) => RecordType::SVCB,
1274            RData::TLSA(..) => RecordType::TLSA,
1275            RData::TXT(..) => RecordType::TXT,
1276            #[cfg(feature = "dnssec")]
1277            RData::DNSSEC(ref rdata) => rdata.to_record_type(),
1278            RData::Unknown { code, .. } => RecordType::Unknown(code),
1279            RData::ZERO => RecordType::ZERO,
1280        }
1281    }
1282
1283    #[test]
1284    fn test_write_to() {
1285        test_emit_data_set(get_data(), |e, d| d.emit(e));
1286    }
1287}