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}