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