hickory_proto/rr/record_data.rs
1// Copyright 2015-2023 Benjamin Fry <benjaminfry@me.com>
2//
3// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
4// https://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
5// https://opensource.org/licenses/MIT>, at your option. This file may not be
6// copied, modified, or distributed except according to those terms.
7
8//! record data enum variants
9#![allow(deprecated, clippy::use_self)] // allows us to deprecate RData types
10
11use alloc::vec::Vec;
12#[cfg(test)]
13use core::convert::From;
14use core::net::{IpAddr, Ipv4Addr, Ipv6Addr};
15use core::{cmp::Ordering, fmt};
16
17#[cfg(feature = "serde")]
18use serde::{Deserialize, Serialize};
19use tracing::{trace, warn};
20
21#[cfg(feature = "__dnssec")]
22use crate::dnssec::rdata::{DNSSECRData, DS};
23use crate::{
24 error::ProtoResult,
25 rr::{
26 Name, RecordData, RecordDataDecodable,
27 rdata::{
28 A, AAAA, ANAME, CAA, CERT, CNAME, CSYNC, HINFO, HTTPS, MX, NAPTR, NS, NULL, OPENPGPKEY,
29 OPT, PTR, SMIMEA, SOA, SRV, SSHFP, SVCB, TLSA, TSIG, TXT,
30 },
31 record_type::RecordType,
32 },
33 serialize::{
34 binary::{BinDecodable, BinDecoder, BinEncodable, BinEncoder, DecodeError, Restrict},
35 txt::{Lexer, ParseError, Token},
36 },
37};
38
39/// Record data enum variants for all valid DNS data types.
40///
41/// This is used to represent the generic Record as it is read off the wire. Allows for a Record to be abstractly referenced without knowing it's internal until runtime.
42///
43/// [RFC 1035](https://tools.ietf.org/html/rfc1035), DOMAIN NAMES - IMPLEMENTATION AND SPECIFICATION, November 1987
44///
45/// ```text
46/// 3.3. Standard RRs
47///
48/// The following RR definitions are expected to occur, at least
49/// potentially, in all classes. In particular, NS, SOA, CNAME, and PTR
50/// will be used in all classes, and have the same format in all classes.
51/// Because their RDATA format is known, all domain names in the RDATA
52/// section of these RRs may be compressed.
53///
54/// <domain-name> is a domain name represented as a series of labels, and
55/// terminated by a label with zero length. <character-string> is a single
56/// length octet followed by that number of characters. <character-string>
57/// is treated as binary information, and can be up to 256 characters in
58/// length (including the length octet).
59/// ```
60#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
61#[derive(Debug, PartialEq, Clone, Eq, Hash)]
62#[non_exhaustive]
63pub enum RData {
64 /// ```text
65 /// -- RFC 1035 -- Domain Implementation and Specification November 1987
66 ///
67 /// 3.4. Internet specific RRs
68 ///
69 /// 3.4.1. A RDATA format
70 ///
71 /// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
72 /// | ADDRESS |
73 /// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
74 ///
75 /// where:
76 ///
77 /// ADDRESS A 32 bit Internet address.
78 ///
79 /// Hosts that have multiple Internet addresses will have multiple A
80 /// records.
81 ///
82 /// A records cause no additional section processing. The RDATA section of
83 /// an A line in a Zone File is an Internet address expressed as four
84 /// decimal numbers separated by dots without any embedded spaces (e.g.,
85 /// "10.2.0.52" or "192.0.5.6").
86 /// ```
87 A(A),
88
89 /// ```text
90 /// -- RFC 1886 -- IPv6 DNS Extensions December 1995
91 ///
92 /// 2.2 AAAA data format
93 ///
94 /// A 128 bit IPv6 address is encoded in the data portion of an AAAA
95 /// resource record in network byte order (high-order byte first).
96 /// ```
97 AAAA(AAAA),
98
99 /// ```text
100 /// 2. The ANAME resource record
101 ///
102 /// This document defines the "ANAME" DNS resource record type, with RR
103 /// TYPE value [TBD].
104 ///
105 /// 2.1. Presentation and wire format
106 ///
107 /// The ANAME presentation format is identical to that of CNAME
108 /// [RFC1033]:
109 ///
110 /// owner ttl class ANAME target
111 /// ```
112 ANAME(ANAME),
113
114 /// ```text
115 /// -- RFC 6844 Certification Authority Authorization January 2013
116 ///
117 /// 5.1. Syntax
118 ///
119 /// A CAA RR contains a single property entry consisting of a tag-value
120 /// pair. Each tag represents a property of the CAA record. The value
121 /// of a CAA property is that specified in the corresponding value field.
122 ///
123 /// A domain name MAY have multiple CAA RRs associated with it and a
124 /// given property MAY be specified more than once.
125 ///
126 /// The CAA data field contains one property entry. A property entry
127 /// consists of the following data fields:
128 ///
129 /// +0-1-2-3-4-5-6-7-|0-1-2-3-4-5-6-7-|
130 /// | Flags | Tag Length = n |
131 /// +----------------+----------------+...+---------------+
132 /// | Tag char 0 | Tag char 1 |...| Tag char n-1 |
133 /// +----------------+----------------+...+---------------+
134 /// +----------------+----------------+.....+----------------+
135 /// | Value byte 0 | Value byte 1 |.....| Value byte m-1 |
136 /// +----------------+----------------+.....+----------------+
137 ///
138 /// Where n is the length specified in the Tag length field and m is the
139 /// remaining octets in the Value field (m = d - n - 2) where d is the
140 /// length of the RDATA section.
141 /// ```
142 CAA(CAA),
143
144 /// ```text
145 /// -- RFC 4398 -- Storing Certificates in DNS November 1987
146 /// The CERT resource record (RR) has the structure given below. Its RR
147 /// type code is 37.
148 ///
149 /// 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
150 /// 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
151 /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
152 /// | type | key tag |
153 /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
154 /// | algorithm | /
155 /// +---------------+ certificate or CRL /
156 /// / /
157 /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-|
158 //// ```
159 CERT(CERT),
160
161 /// ```text
162 /// 3.3. Standard RRs
163 ///
164 /// The following RR definitions are expected to occur, at least
165 /// potentially, in all classes. In particular, NS, SOA, CNAME, and PTR
166 /// will be used in all classes, and have the same format in all classes.
167 /// Because their RDATA format is known, all domain names in the RDATA
168 /// section of these RRs may be compressed.
169 ///
170 /// <domain-name> is a domain name represented as a series of labels, and
171 /// terminated by a label with zero length. <character-string> is a single
172 /// length octet followed by that number of characters. <character-string>
173 /// is treated as binary information, and can be up to 256 characters in
174 /// length (including the length octet).
175 ///
176 /// 3.3.1. CNAME RDATA format
177 ///
178 /// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
179 /// / CNAME /
180 /// / /
181 /// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
182 ///
183 /// where:
184 ///
185 /// CNAME A <domain-name> which specifies the canonical or primary
186 /// name for the owner. The owner name is an alias.
187 ///
188 /// CNAME RRs cause no additional section processing, but name servers may
189 /// choose to restart the query at the canonical name in certain cases. See
190 /// the description of name server logic in [RFC-1034] for details.
191 /// ```
192 CNAME(CNAME),
193
194 /// ```text
195 /// 2.1. The CSYNC Resource Record Format
196 ///
197 /// 2.1.1. The CSYNC Resource Record Wire Format
198 ///
199 /// The CSYNC RDATA consists of the following fields:
200 ///
201 /// 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
202 /// 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
203 /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
204 /// | SOA Serial |
205 /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
206 /// | Flags | Type Bit Map /
207 /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
208 /// / Type Bit Map (continued) /
209 /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
210 /// ```
211 CSYNC(CSYNC),
212
213 /// ```text
214 /// 3.3.2. HINFO RDATA format
215 ///
216 /// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
217 /// / CPU /
218 /// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
219 /// / OS /
220 /// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
221 ///
222 /// where:
223 ///
224 /// CPU A <character-string> which specifies the CPU type.
225 ///
226 /// OS A <character-string> which specifies the operating
227 /// system type.
228 ///
229 /// Standard values for CPU and OS can be found in [RFC-1010].
230 ///
231 /// HINFO records are used to acquire general information about a host. The
232 /// main use is for protocols such as FTP that can use special procedures
233 /// when talking between machines or operating systems of the same type.
234 /// ```
235 ///
236 /// `HINFO` is also used by [RFC 8482](https://tools.ietf.org/html/rfc8482)
237 HINFO(HINFO),
238
239 /// [RFC 9460, SVCB and HTTPS RRs](https://datatracker.ietf.org/doc/html/rfc9460#section-9)
240 ///
241 /// ```text
242 /// 9. Using Service Bindings with HTTP
243 ///
244 /// The use of any protocol with SVCB requires a protocol-specific
245 /// mapping specification. This section specifies the mapping for the
246 /// "http" and "https" URI schemes [HTTP].
247 ///
248 /// To enable special handling for HTTP use cases, the HTTPS RR type is
249 /// defined as a SVCB-compatible RR type, specific to the "https" and
250 /// "http" schemes. Clients MUST NOT perform SVCB queries or accept SVCB
251 /// responses for "https" or "http" schemes.
252 ///
253 /// The presentation format of the record is:
254 ///
255 /// Name TTL IN HTTPS SvcPriority TargetName SvcParams
256 /// ```
257 HTTPS(HTTPS),
258
259 /// ```text
260 /// 3.3.9. MX RDATA format
261 ///
262 /// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
263 /// | PREFERENCE |
264 /// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
265 /// / EXCHANGE /
266 /// / /
267 /// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
268 ///
269 /// where:
270 ///
271 /// PREFERENCE A 16 bit integer which specifies the preference given to
272 /// this RR among others at the same owner. Lower values
273 /// are preferred.
274 ///
275 /// EXCHANGE A <domain-name> which specifies a host willing to act as
276 /// a mail exchange for the owner name.
277 ///
278 /// MX records cause type A additional section processing for the host
279 /// specified by EXCHANGE. The use of MX RRs is explained in detail in
280 /// [RFC-974].
281 /// ```
282 MX(MX),
283
284 /// [RFC 3403 DDDS DNS Database, October 2002](https://tools.ietf.org/html/rfc3403#section-4)
285 ///
286 /// ```text
287 /// 4.1 Packet Format
288 ///
289 /// The packet format of the NAPTR RR is given below. The DNS type code
290 /// for NAPTR is 35.
291 ///
292 /// The packet format for the NAPTR record is as follows
293 /// 1 1 1 1 1 1
294 /// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
295 /// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
296 /// | ORDER |
297 /// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
298 /// | PREFERENCE |
299 /// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
300 /// / FLAGS /
301 /// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
302 /// / SERVICES /
303 /// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
304 /// / REGEXP /
305 /// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
306 /// / REPLACEMENT /
307 /// / /
308 /// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
309 ///
310 /// <character-string> and <domain-name> as used here are defined in RFC
311 /// 1035 [7].
312 ///
313 /// ORDER
314 /// A 16-bit unsigned integer specifying the order in which the NAPTR
315 /// records MUST be processed in order to accurately represent the
316 /// ordered list of Rules. The ordering is from lowest to highest.
317 /// If two records have the same order value then they are considered
318 /// to be the same rule and should be selected based on the
319 /// combination of the Preference values and Services offered.
320 ///
321 /// PREFERENCE
322 /// Although it is called "preference" in deference to DNS
323 /// terminology, this field is equivalent to the Priority value in the
324 /// DDDS Algorithm. It is a 16-bit unsigned integer that specifies
325 /// the order in which NAPTR records with equal Order values SHOULD be
326 /// processed, low numbers being processed before high numbers. This
327 /// is similar to the preference field in an MX record, and is used so
328 /// domain administrators can direct clients towards more capable
329 /// hosts or lighter weight protocols. A client MAY look at records
330 /// with higher preference values if it has a good reason to do so
331 /// such as not supporting some protocol or service very well.
332 ///
333 /// The important difference between Order and Preference is that once
334 /// a match is found the client MUST NOT consider records with a
335 /// different Order but they MAY process records with the same Order
336 /// but different Preferences. The only exception to this is noted in
337 /// the second important Note in the DDDS algorithm specification
338 /// concerning allowing clients to use more complex Service
339 /// determination between steps 3 and 4 in the algorithm. Preference
340 /// is used to give communicate a higher quality of service to rules
341 /// that are considered the same from an authority standpoint but not
342 /// from a simple load balancing standpoint.
343 ///
344 /// It is important to note that DNS contains several load balancing
345 /// mechanisms and if load balancing among otherwise equal services
346 /// should be needed then methods such as SRV records or multiple A
347 /// records should be utilized to accomplish load balancing.
348 ///
349 /// FLAGS
350 /// A <character-string> containing flags to control aspects of the
351 /// rewriting and interpretation of the fields in the record. Flags
352 /// are single characters from the set A-Z and 0-9. The case of the
353 /// alphabetic characters is not significant. The field can be empty.
354 ///
355 /// It is up to the Application specifying how it is using this
356 /// Database to define the Flags in this field. It must define which
357 /// ones are terminal and which ones are not.
358 ///
359 /// SERVICES
360 /// A <character-string> that specifies the Service Parameters
361 /// applicable to this this delegation path. It is up to the
362 /// Application Specification to specify the values found in this
363 /// field.
364 ///
365 /// REGEXP
366 /// A <character-string> containing a substitution expression that is
367 /// applied to the original string held by the client in order to
368 /// construct the next domain name to lookup. See the DDDS Algorithm
369 /// specification for the syntax of this field.
370 ///
371 /// As stated in the DDDS algorithm, The regular expressions MUST NOT
372 /// be used in a cumulative fashion, that is, they should only be
373 /// applied to the original string held by the client, never to the
374 /// domain name produced by a previous NAPTR rewrite. The latter is
375 /// tempting in some applications but experience has shown such use to
376 /// be extremely fault sensitive, very error prone, and extremely
377 /// difficult to debug.
378 ///
379 /// REPLACEMENT
380 /// A <domain-name> which is the next domain-name to query for
381 /// depending on the potential values found in the flags field. This
382 /// field is used when the regular expression is a simple replacement
383 /// operation. Any value in this field MUST be a fully qualified
384 /// domain-name. Name compression is not to be used for this field.
385 ///
386 /// This field and the REGEXP field together make up the Substitution
387 /// Expression in the DDDS Algorithm. It is simply a historical
388 /// optimization specifically for DNS compression that this field
389 /// exists. The fields are also mutually exclusive. If a record is
390 /// returned that has values for both fields then it is considered to
391 /// be in error and SHOULD be either ignored or an error returned.
392 /// ```
393 NAPTR(NAPTR),
394
395 /// ```text
396 /// 3.3.10. NULL RDATA format (EXPERIMENTAL)
397 ///
398 /// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
399 /// / <anything> /
400 /// / /
401 /// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
402 ///
403 /// Anything at all may be in the RDATA field so long as it is 65535 octets
404 /// or less.
405 ///
406 /// NULL records cause no additional section processing. NULL RRs are not
407 /// allowed in Zone Files. NULLs are used as placeholders in some
408 /// experimental extensions of the DNS.
409 /// ```
410 NULL(NULL),
411
412 /// ```text
413 /// 3.3.11. NS RDATA format
414 ///
415 /// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
416 /// / NSDNAME /
417 /// / /
418 /// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
419 ///
420 /// where:
421 ///
422 /// NSDNAME A <domain-name> which specifies a host which should be
423 /// authoritative for the specified class and domain.
424 ///
425 /// NS records cause both the usual additional section processing to locate
426 /// a type A record, and, when used in a referral, a special search of the
427 /// zone in which they reside for glue information.
428 ///
429 /// The NS RR states that the named host should be expected to have a zone
430 /// starting at owner name of the specified class. Note that the class may
431 /// not indicate the protocol family which should be used to communicate
432 /// with the host, although it is typically a strong hint. For example,
433 /// hosts which are name servers for either Internet (IN) or Hesiod (HS)
434 /// class information are normally queried using IN class protocols.
435 /// ```
436 NS(NS),
437
438 /// [RFC 7929](https://tools.ietf.org/html/rfc7929#section-2.1)
439 ///
440 /// ```text
441 /// The RDATA portion of an OPENPGPKEY resource record contains a single
442 /// value consisting of a Transferable Public Key formatted as specified
443 /// in [RFC4880].
444 /// ```
445 OPENPGPKEY(OPENPGPKEY),
446
447 /// ```text
448 /// RFC 6891 EDNS(0) Extensions April 2013
449 /// 6.1.2. Wire Format
450 ///
451 /// +------------+--------------+------------------------------+
452 /// | Field Name | Field Type | Description |
453 /// +------------+--------------+------------------------------+
454 /// | NAME | domain name | MUST be 0 (root domain) |
455 /// | TYPE | u_int16_t | OPT (41) |
456 /// | CLASS | u_int16_t | requestor's UDP payload size |
457 /// | TTL | u_int32_t | extended RCODE and flags |
458 /// | RDLEN | u_int16_t | length of all RDATA |
459 /// | RDATA | octet stream | {attribute,value} pairs |
460 /// +------------+--------------+------------------------------+
461 ///
462 /// The variable part of an OPT RR may contain zero or more options in
463 /// the RDATA. Each option MUST be treated as a bit field. Each option
464 /// is encoded as:
465 ///
466 /// +0 (MSB) +1 (LSB)
467 /// +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
468 /// 0: | OPTION-CODE |
469 /// +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
470 /// 2: | OPTION-LENGTH |
471 /// +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
472 /// 4: | |
473 /// / OPTION-DATA /
474 /// / /
475 /// +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
476 /// ```
477 OPT(OPT),
478
479 /// ```text
480 /// 3.3.12. PTR RDATA format
481 ///
482 /// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
483 /// / PTRDNAME /
484 /// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
485 ///
486 /// where:
487 ///
488 /// PTRDNAME A <domain-name> which points to some location in the
489 /// domain name space.
490 ///
491 /// PTR records cause no additional section processing. These RRs are used
492 /// in special domains to point to some other location in the domain space.
493 /// These records are simple data, and don't imply any special processing
494 /// similar to that performed by CNAME, which identifies aliases. See the
495 /// description of the IN-ADDR.ARPA domain for an example.
496 /// ```
497 PTR(PTR),
498
499 /// [RFC 8162](https://datatracker.ietf.org/doc/html/rfc8162#section-2)
500 ///
501 /// > The SMIMEA wire format and presentation format are the same as for
502 /// > the [TLSA](Self::TLSA) record
503 SMIMEA(SMIMEA),
504
505 /// ```text
506 /// 3.3.13. SOA RDATA format
507 ///
508 /// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
509 /// / MNAME /
510 /// / /
511 /// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
512 /// / RNAME /
513 /// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
514 /// | SERIAL |
515 /// | |
516 /// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
517 /// | REFRESH |
518 /// | |
519 /// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
520 /// | RETRY |
521 /// | |
522 /// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
523 /// | EXPIRE |
524 /// | |
525 /// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
526 /// | MINIMUM |
527 /// | |
528 /// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
529 ///
530 /// where:
531 ///
532 /// MNAME The <domain-name> of the name server that was the
533 /// original or primary source of data for this zone.
534 ///
535 /// RNAME A <domain-name> which specifies the mailbox of the
536 /// person responsible for this zone.
537 ///
538 /// SERIAL The unsigned 32 bit version number of the original copy
539 /// of the zone. Zone transfers preserve this value. This
540 /// value wraps and should be compared using sequence space
541 /// arithmetic.
542 ///
543 /// REFRESH A 32 bit time interval before the zone should be
544 /// refreshed.
545 ///
546 /// RETRY A 32 bit time interval that should elapse before a
547 /// failed refresh should be retried.
548 ///
549 /// EXPIRE A 32 bit time value that specifies the upper limit on
550 /// the time interval that can elapse before the zone is no
551 /// longer authoritative.
552 ///
553 /// MINIMUM The unsigned 32 bit minimum TTL field that should be
554 /// exported with any RR from this zone.
555 ///
556 /// SOA records cause no additional section processing.
557 ///
558 /// All times are in units of seconds.
559 ///
560 /// Most of these fields are pertinent only for name server maintenance
561 /// operations. However, MINIMUM is used in all query operations that
562 /// retrieve RRs from a zone. Whenever a RR is sent in a response to a
563 /// query, the TTL field is set to the maximum of the TTL field from the RR
564 /// and the MINIMUM field in the appropriate SOA. Thus MINIMUM is a lower
565 /// bound on the TTL field for all RRs in a zone. Note that this use of
566 /// MINIMUM should occur when the RRs are copied into the response and not
567 /// when the zone is loaded from a Zone File or via a zone transfer. The
568 /// reason for this provision is to allow future dynamic update facilities to
569 /// change the SOA RR with known semantics.
570 /// ```
571 SOA(SOA),
572
573 /// ```text
574 /// RFC 2782 DNS SRV RR February 2000
575 ///
576 /// The format of the SRV RR
577 ///
578 /// _Service._Proto.Name TTL Class SRV Priority Weight Port Target
579 /// ```
580 SRV(SRV),
581
582 /// [RFC 4255](https://tools.ietf.org/html/rfc4255#section-3.1)
583 ///
584 /// ```text
585 /// 3.1. The SSHFP RDATA Format
586 ///
587 /// The RDATA for a SSHFP RR consists of an algorithm number, fingerprint
588 /// type and the fingerprint of the public host key.
589 ///
590 /// 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
591 /// 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
592 /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
593 /// | algorithm | fp type | /
594 /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ /
595 /// / /
596 /// / fingerprint /
597 /// / /
598 /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
599 ///
600 /// 3.1.1. Algorithm Number Specification
601 ///
602 /// This algorithm number octet describes the algorithm of the public
603 /// key. The following values are assigned:
604 ///
605 /// Value Algorithm name
606 /// ----- --------------
607 /// 0 reserved
608 /// 1 RSA
609 /// 2 DSS
610 ///
611 /// Reserving other types requires IETF consensus [4].
612 ///
613 /// 3.1.2. Fingerprint Type Specification
614 ///
615 /// The fingerprint type octet describes the message-digest algorithm
616 /// used to calculate the fingerprint of the public key. The following
617 /// values are assigned:
618 ///
619 /// Value Fingerprint type
620 /// ----- ----------------
621 /// 0 reserved
622 /// 1 SHA-1
623 ///
624 /// Reserving other types requires IETF consensus [4].
625 ///
626 /// For interoperability reasons, as few fingerprint types as possible
627 /// should be reserved. The only reason to reserve additional types is
628 /// to increase security.
629 ///
630 /// 3.1.3. Fingerprint
631 ///
632 /// The fingerprint is calculated over the public key blob as described
633 /// in [7].
634 ///
635 /// The message-digest algorithm is presumed to produce an opaque octet
636 /// string output, which is placed as-is in the RDATA fingerprint field.
637 /// ```
638 ///
639 /// The algorithm and fingerprint type values have been updated in
640 /// [RFC 6594](https://tools.ietf.org/html/rfc6594) and
641 /// [RFC 7479](https://tools.ietf.org/html/rfc7479).
642 SSHFP(SSHFP),
643
644 /// [RFC 9460, SVCB and HTTPS RRs](https://datatracker.ietf.org/doc/html/rfc9460#section-2)
645 ///
646 /// ```text
647 /// 2. The SVCB Record Type
648 ///
649 /// The SVCB DNS RR type (RR type 64) is used to locate alternative
650 /// endpoints for a service.
651 ///
652 /// The algorithm for resolving SVCB records and associated address
653 /// records is specified in Section 3.
654 ///
655 /// Other SVCB-compatible RR types can also be defined as needed (see
656 /// Section 6). In particular, the HTTPS RR (RR type 65) provides
657 /// special handling for the case of "https" origins as described in
658 /// Section 9.
659 ///
660 /// SVCB RRs are extensible by a list of SvcParams, which are pairs
661 /// consisting of a SvcParamKey and a SvcParamValue. Each SvcParamKey
662 /// has a presentation name and a registered number. Values are in a
663 /// format specific to the SvcParamKey. Each SvcParam has a specified
664 /// presentation format (used in zone files) and wire encoding (e.g.,
665 /// domain names, binary data, or numeric values). The initial
666 /// SvcParamKeys and their formats are defined in Section 7.
667 /// ```
668 SVCB(SVCB),
669
670 /// [RFC 6698, DNS-Based Authentication for TLS](https://tools.ietf.org/html/rfc6698#section-2.1)
671 ///
672 /// ```text
673 /// 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
674 /// 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
675 /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
676 /// | Cert. Usage | Selector | Matching Type | /
677 /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ /
678 /// / /
679 /// / Certificate Association Data /
680 /// / /
681 /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
682 /// ```
683 TLSA(TLSA),
684
685 /// [RFC 8945, Secret Key Transaction Authentication for DNS](https://tools.ietf.org/html/rfc8945#section-4.2)
686 ///
687 /// ```text
688 /// 4.2. TSIG Record Format
689 ///
690 /// The fields of the TSIG RR are described below. All multi-octet
691 /// integers in the record are sent in network byte order (see
692 /// Section 2.3.2 of [RFC1035]).
693 ///
694 /// NAME: The name of the key used, in domain name syntax. The name
695 /// should reflect the names of the hosts and uniquely identify the
696 /// key among a set of keys these two hosts may share at any given
697 /// time. For example, if hosts A.site.example and B.example.net
698 /// share a key, possibilities for the key name include
699 /// <id>.A.site.example, <id>.B.example.net, and
700 /// <id>.A.site.example.B.example.net. It should be possible for more
701 /// than one key to be in simultaneous use among a set of interacting
702 /// hosts. This allows for periodic key rotation as per best
703 /// operational practices, as well as algorithm agility as indicated
704 /// by [RFC7696].
705 ///
706 /// The name may be used as a local index to the key involved, but it
707 /// is recommended that it be globally unique. Where a key is just
708 /// shared between two hosts, its name actually need only be
709 /// meaningful to them, but it is recommended that the key name be
710 /// mnemonic and incorporate the names of participating agents or
711 /// resources as suggested above.
712 ///
713 /// TYPE: This MUST be TSIG (250: Transaction SIGnature).
714 ///
715 /// CLASS: This MUST be ANY.
716 ///
717 /// TTL: This MUST be 0.
718 ///
719 /// RDLENGTH: (variable)
720 ///
721 /// RDATA: The RDATA for a TSIG RR consists of a number of fields,
722 /// described below:
723 ///
724 /// 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
725 /// 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
726 /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
727 /// / Algorithm Name /
728 /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
729 /// | |
730 /// | Time Signed +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
731 /// | | Fudge |
732 /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
733 /// | MAC Size | /
734 /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ MAC /
735 /// / /
736 /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
737 /// | Original ID | Error |
738 /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
739 /// | Other Len | /
740 /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ Other Data /
741 /// / /
742 /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
743 ///
744 /// The contents of the RDATA fields are:
745 ///
746 /// Algorithm Name:
747 /// an octet sequence identifying the TSIG algorithm in the domain
748 /// name syntax. (Allowed names are listed in Table 3.) The name is
749 /// stored in the DNS name wire format as described in [RFC1034]. As
750 /// per [RFC3597], this name MUST NOT be compressed.
751 ///
752 /// Time Signed:
753 /// an unsigned 48-bit integer containing the time the message was
754 /// signed as seconds since 00:00 on 1970-01-01 UTC, ignoring leap
755 /// seconds.
756 ///
757 /// Fudge:
758 /// an unsigned 16-bit integer specifying the allowed time difference
759 /// in seconds permitted in the Time Signed field.
760 ///
761 /// MAC Size:
762 /// an unsigned 16-bit integer giving the length of the MAC field in
763 /// octets. Truncation is indicated by a MAC Size less than the size
764 /// of the keyed hash produced by the algorithm specified by the
765 /// Algorithm Name.
766 ///
767 /// MAC:
768 /// a sequence of octets whose contents are defined by the TSIG
769 /// algorithm used, possibly truncated as specified by the MAC Size.
770 /// The length of this field is given by the MAC Size. Calculation of
771 /// the MAC is detailed in Section 4.3.
772 ///
773 /// Original ID:
774 /// an unsigned 16-bit integer holding the message ID of the original
775 /// request message. For a TSIG RR on a request, it is set equal to
776 /// the DNS message ID. In a TSIG attached to a response -- or in
777 /// cases such as the forwarding of a dynamic update request -- the
778 /// field contains the ID of the original DNS request.
779 ///
780 /// Error:
781 /// in responses, an unsigned 16-bit integer containing the extended
782 /// RCODE covering TSIG processing. In requests, this MUST be zero.
783 ///
784 /// Other Len:
785 /// an unsigned 16-bit integer specifying the length of the Other Data
786 /// field in octets.
787 ///
788 /// Other Data:
789 /// additional data relevant to the TSIG record. In responses, this
790 /// will be empty (i.e., Other Len will be zero) unless the content of
791 /// the Error field is BADTIME, in which case it will be a 48-bit
792 /// unsigned integer containing the server's current time as the
793 /// number of seconds since 00:00 on 1970-01-01 UTC, ignoring leap
794 /// seconds (see Section 5.2.3). This document assigns no meaning to
795 /// its contents in requests.
796 /// ```
797 TSIG(TSIG),
798
799 /// ```text
800 /// 3.3.14. TXT RDATA format
801 ///
802 /// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
803 /// / TXT-DATA /
804 /// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
805 ///
806 /// where:
807 ///
808 /// TXT-DATA One or more <character-string>s.
809 ///
810 /// TXT RRs are used to hold descriptive text. The semantics of the text
811 /// depends on the domain where it is found.
812 /// ```
813 TXT(TXT),
814
815 /// A DNSSEC- or SIG(0)- specific record. See `DNSSECRData` for details.
816 ///
817 /// These types are in `DNSSECRData` to make them easy to disable when
818 /// crypto functionality isn't needed.
819 #[cfg(feature = "__dnssec")]
820 DNSSEC(DNSSECRData),
821
822 /// Unknown RecordData is for record types not supported by Hickory DNS
823 Unknown {
824 /// RecordType code
825 code: RecordType,
826 /// RData associated to the record
827 rdata: NULL,
828 },
829
830 /// Update record with RDLENGTH = 0 (RFC2136)
831 Update0(RecordType),
832
833 /// This corresponds to a record type of 0, unspecified
834 #[deprecated(note = "Use None for the RData in the resource record instead")]
835 ZERO,
836}
837
838impl RData {
839 fn to_bytes(&self) -> Vec<u8> {
840 let mut buf: Vec<u8> = Vec::new();
841 {
842 let mut encoder: BinEncoder<'_> = BinEncoder::new(&mut buf);
843 self.emit(&mut encoder).unwrap_or_else(|_| {
844 warn!("could not encode RDATA: {:?}", self);
845 });
846 }
847 buf
848 }
849
850 /// Converts this to a Recordtype
851 pub fn record_type(&self) -> RecordType {
852 match self {
853 Self::A(..) => RecordType::A,
854 Self::AAAA(..) => RecordType::AAAA,
855 Self::ANAME(..) => RecordType::ANAME,
856 Self::CAA(..) => RecordType::CAA,
857 Self::CERT(..) => RecordType::CERT,
858 Self::CNAME(..) => RecordType::CNAME,
859 Self::CSYNC(..) => RecordType::CSYNC,
860 Self::HINFO(..) => RecordType::HINFO,
861 Self::HTTPS(..) => RecordType::HTTPS,
862 Self::MX(..) => RecordType::MX,
863 Self::NAPTR(..) => RecordType::NAPTR,
864 Self::NS(..) => RecordType::NS,
865 Self::NULL(..) => RecordType::NULL,
866 Self::OPENPGPKEY(..) => RecordType::OPENPGPKEY,
867 Self::OPT(..) => RecordType::OPT,
868 Self::PTR(..) => RecordType::PTR,
869 Self::SMIMEA(..) => RecordType::SMIMEA,
870 Self::SOA(..) => RecordType::SOA,
871 Self::SRV(..) => RecordType::SRV,
872 Self::SSHFP(..) => RecordType::SSHFP,
873 Self::SVCB(..) => RecordType::SVCB,
874 Self::TLSA(..) => RecordType::TLSA,
875 Self::TSIG(..) => RecordType::TSIG,
876 Self::TXT(..) => RecordType::TXT,
877 #[cfg(feature = "__dnssec")]
878 Self::DNSSEC(rdata) => DNSSECRData::to_record_type(rdata),
879 Self::Unknown { code, .. } => *code,
880 Self::Update0(record_type) => *record_type,
881 Self::ZERO => RecordType::ZERO,
882 }
883 }
884
885 /// If this is an A or AAAA record type, then an IpAddr will be returned
886 pub fn ip_addr(&self) -> Option<IpAddr> {
887 match self {
888 Self::A(a) => Some(IpAddr::from(a.0)),
889 Self::AAAA(aaaa) => Some(IpAddr::from(aaaa.0)),
890 _ => None,
891 }
892 }
893
894 /// Read data from the decoder
895 pub fn read(
896 decoder: &mut BinDecoder<'_>,
897 record_type: RecordType,
898 length: Restrict<u16>,
899 ) -> Result<Self, DecodeError> {
900 let start_idx = decoder.index();
901
902 let result = match record_type {
903 RecordType::A => {
904 trace!("reading A");
905 A::read(decoder).map(Self::A)
906 }
907 RecordType::AAAA => {
908 trace!("reading AAAA");
909 AAAA::read(decoder).map(Self::AAAA)
910 }
911 RecordType::ANAME => {
912 trace!("reading ANAME");
913 ANAME::read(decoder).map(Self::ANAME)
914 }
915 rt @ RecordType::ANY | rt @ RecordType::AXFR | rt @ RecordType::IXFR => {
916 return Err(DecodeError::UnknownRecordTypeValue(rt.into()));
917 }
918 RecordType::CAA => {
919 trace!("reading CAA");
920 CAA::read_data(decoder, length).map(Self::CAA)
921 }
922 RecordType::CERT => {
923 trace!("reading CERT");
924 CERT::read_data(decoder, length).map(Self::CERT)
925 }
926 RecordType::CNAME => {
927 trace!("reading CNAME");
928 CNAME::read(decoder).map(Self::CNAME)
929 }
930 RecordType::CSYNC => {
931 trace!("reading CSYNC");
932 CSYNC::read_data(decoder, length).map(Self::CSYNC)
933 }
934 RecordType::HINFO => {
935 trace!("reading HINFO");
936 HINFO::read_data(decoder, length).map(Self::HINFO)
937 }
938 RecordType::HTTPS => {
939 trace!("reading HTTPS");
940 HTTPS::read_data(decoder, length).map(Self::HTTPS)
941 }
942 RecordType::ZERO => {
943 trace!("reading EMPTY");
944 // we should never get here, since ZERO should be 0 length, and None in the Record.
945 // this invariant is verified below, and the decoding will fail with an err.
946 #[allow(deprecated)]
947 Ok(Self::ZERO)
948 }
949 RecordType::MX => {
950 trace!("reading MX");
951 MX::read_data(decoder, length).map(Self::MX)
952 }
953 RecordType::NAPTR => {
954 trace!("reading NAPTR");
955 NAPTR::read_data(decoder, length).map(Self::NAPTR)
956 }
957 RecordType::NULL => {
958 trace!("reading NULL");
959 NULL::read_data(decoder, length).map(Self::NULL)
960 }
961 RecordType::NS => {
962 trace!("reading NS");
963 NS::read(decoder).map(Self::NS)
964 }
965 RecordType::OPENPGPKEY => {
966 trace!("reading OPENPGPKEY");
967 OPENPGPKEY::read_data(decoder, length).map(Self::OPENPGPKEY)
968 }
969 RecordType::OPT => {
970 trace!("reading OPT");
971 OPT::read_data(decoder, length).map(Self::OPT)
972 }
973 RecordType::PTR => {
974 trace!("reading PTR");
975 PTR::read(decoder).map(Self::PTR)
976 }
977 RecordType::SMIMEA => {
978 trace!("reading SMIMEA");
979 SMIMEA::read_data(decoder, length).map(Self::SMIMEA)
980 }
981 RecordType::SOA => {
982 trace!("reading SOA");
983 SOA::read_data(decoder, length).map(Self::SOA)
984 }
985 RecordType::SRV => {
986 trace!("reading SRV");
987 SRV::read_data(decoder, length).map(Self::SRV)
988 }
989 RecordType::SSHFP => {
990 trace!("reading SSHFP");
991 SSHFP::read_data(decoder, length).map(Self::SSHFP)
992 }
993 RecordType::SVCB => {
994 trace!("reading SVCB");
995 SVCB::read_data(decoder, length).map(Self::SVCB)
996 }
997 RecordType::TLSA => {
998 trace!("reading TLSA");
999 TLSA::read_data(decoder, length).map(Self::TLSA)
1000 }
1001 RecordType::TSIG => {
1002 trace!("reading TSIG");
1003 TSIG::read_data(decoder, length).map(Self::TSIG)
1004 }
1005 RecordType::TXT => {
1006 trace!("reading TXT");
1007 TXT::read_data(decoder, length).map(Self::TXT)
1008 }
1009 #[cfg(feature = "__dnssec")]
1010 r if r.is_dnssec() => DNSSECRData::read(decoder, record_type, length).map(Self::DNSSEC),
1011 record_type => {
1012 trace!("reading Unknown record: {}", record_type);
1013 NULL::read_data(decoder, length).map(|rdata| Self::Unknown {
1014 code: record_type,
1015 rdata,
1016 })
1017 }
1018 };
1019
1020 // we should have read rdata_length, but we did not
1021 let read = decoder.index() - start_idx;
1022 length
1023 .map(|u| u as usize)
1024 .verify_unwrap(|rdata_length| read == *rdata_length)
1025 .map_err(|rdata_length| DecodeError::IncorrectRDataLengthRead {
1026 read,
1027 len: rdata_length,
1028 })?;
1029
1030 result
1031 }
1032
1033 /// Parse RData from a string
1034 pub fn try_from_str(record_type: RecordType, s: &str) -> Result<Self, ParseError> {
1035 let mut lexer = Lexer::new(s);
1036 let mut rdata = Vec::new();
1037
1038 while let Some(token) = lexer.next_token()? {
1039 match token {
1040 Token::List(list) => rdata.extend(list),
1041 Token::CharData(s) => rdata.push(s),
1042 Token::EOL | Token::Blank => (),
1043 _ => {
1044 return Err(ParseError::from(format!(
1045 "unexpected token in record data: {token:?}"
1046 )));
1047 }
1048 }
1049 }
1050
1051 Self::from_tokens(record_type, rdata.iter().map(AsRef::as_ref), None)
1052 }
1053
1054 /// Attempts to parse a stream of tokenized strs into the RData of the specified record type
1055 /// Parse the RData from a set of Tokens
1056 pub(crate) fn from_tokens<'i, I: Iterator<Item = &'i str>>(
1057 record_type: RecordType,
1058 tokens: I,
1059 origin: Option<&Name>,
1060 ) -> Result<Self, ParseError> {
1061 let rdata = match record_type {
1062 RecordType::A => Self::A(A::from_tokens(tokens)?),
1063 RecordType::AAAA => Self::AAAA(AAAA::from_tokens(tokens)?),
1064 RecordType::ANAME => Self::ANAME(ANAME(Name::from_tokens(tokens, origin)?)),
1065 RecordType::ANY => return Err(ParseError::from("parsing ANY doesn't make sense")),
1066 RecordType::AXFR => return Err(ParseError::from("parsing AXFR doesn't make sense")),
1067 RecordType::CAA => Self::CAA(CAA::from_tokens(tokens)?),
1068 RecordType::CERT => Self::CERT(CERT::from_tokens(tokens)?),
1069 RecordType::CNAME => Self::CNAME(CNAME(Name::from_tokens(tokens, origin)?)),
1070 RecordType::CSYNC => Self::CSYNC(CSYNC::from_tokens(tokens)?),
1071 RecordType::HINFO => Self::HINFO(HINFO::from_tokens(tokens)?),
1072 RecordType::HTTPS => Self::HTTPS(HTTPS(SVCB::from_tokens(tokens)?)),
1073 RecordType::IXFR => return Err(ParseError::from("parsing IXFR doesn't make sense")),
1074 RecordType::MX => Self::MX(MX::from_tokens(tokens, origin)?),
1075 RecordType::NAPTR => Self::NAPTR(NAPTR::from_tokens(tokens, origin)?),
1076 RecordType::NULL => {
1077 return Err(ParseError::Message(
1078 "parse is not implemented for NULL record",
1079 ));
1080 }
1081 RecordType::NS => Self::NS(NS(Name::from_tokens(tokens, origin)?)),
1082 RecordType::OPENPGPKEY => Self::OPENPGPKEY(OPENPGPKEY::from_tokens(tokens)?),
1083 RecordType::OPT => return Err(ParseError::from("parsing OPT doesn't make sense")),
1084 RecordType::PTR => Self::PTR(PTR(Name::from_tokens(tokens, origin)?)),
1085 RecordType::SMIMEA => Self::SMIMEA(SMIMEA::from_tokens(tokens)?),
1086 RecordType::SOA => Self::SOA(SOA::from_tokens(tokens, origin)?),
1087 RecordType::SRV => Self::SRV(SRV::from_tokens(tokens, origin)?),
1088 RecordType::SSHFP => Self::SSHFP(SSHFP::from_tokens(tokens)?),
1089 RecordType::SVCB => Self::SVCB(SVCB::from_tokens(tokens)?),
1090 RecordType::TLSA => Self::TLSA(TLSA::from_tokens(tokens)?),
1091 RecordType::TXT => Self::TXT(TXT::from_tokens(tokens)?),
1092 RecordType::SIG => return Err(ParseError::from("parsing SIG doesn't make sense")),
1093 RecordType::DNSKEY => {
1094 return Err(ParseError::from("DNSKEY should be dynamically generated"));
1095 }
1096 RecordType::CDNSKEY => {
1097 return Err(ParseError::from("CDNSKEY should be dynamically generated"));
1098 }
1099 RecordType::KEY => return Err(ParseError::from("KEY should be dynamically generated")),
1100 #[cfg(feature = "__dnssec")]
1101 RecordType::DS => Self::DNSSEC(DNSSECRData::DS(DS::from_tokens(tokens)?)),
1102 #[cfg(not(feature = "__dnssec"))]
1103 RecordType::DS => return Err(ParseError::from("DS should be dynamically generated")),
1104 RecordType::CDS => return Err(ParseError::from("CDS should be dynamically generated")),
1105 RecordType::NSEC => {
1106 return Err(ParseError::from("NSEC should be dynamically generated"));
1107 }
1108 RecordType::NSEC3 => {
1109 return Err(ParseError::from("NSEC3 should be dynamically generated"));
1110 }
1111 RecordType::NSEC3PARAM => {
1112 return Err(ParseError::from(
1113 "NSEC3PARAM should be dynamically generated",
1114 ));
1115 }
1116 RecordType::RRSIG => {
1117 return Err(ParseError::from("RRSIG should be dynamically generated"));
1118 }
1119 RecordType::TSIG => return Err(ParseError::from("TSIG is only used during AXFR")),
1120 #[allow(deprecated)]
1121 RecordType::ZERO => Self::ZERO,
1122 r @ RecordType::Unknown(..) => {
1123 // TODO: add a way to associate generic record types to the zone
1124 return Err(ParseError::UnsupportedRecordType(r));
1125 }
1126 };
1127
1128 Ok(rdata)
1129 }
1130}
1131
1132impl BinEncodable for RData {
1133 /// [RFC 4034](https://tools.ietf.org/html/rfc4034#section-6), DNSSEC Resource Records, March 2005
1134 ///
1135 /// ```text
1136 /// 6.2. Canonical RR Form
1137 ///
1138 /// For the purposes of DNS security, the canonical form of an RR is the
1139 /// wire format of the RR where:
1140 ///
1141 /// ...
1142 ///
1143 /// 3. if the type of the RR is NS, MD, MF, CNAME, SOA, MB, MG, MR, PTR,
1144 /// HINFO, MINFO, MX, HINFO, RP, AFSDB, RT, SIG, PX, NXT, NAPTR, KX,
1145 /// SRV, DNAME, A6, RRSIG, or (rfc6840 removes NSEC), all uppercase
1146 /// US-ASCII letters in the DNS names contained within the RDATA are replaced
1147 /// by the corresponding lowercase US-ASCII letters;
1148 /// ```
1149 ///
1150 /// Canonical name form for all non-1035 records:
1151 /// [RFC 3597](https://tools.ietf.org/html/rfc3597)
1152 /// ```text
1153 /// 4. Domain Name Compression
1154 ///
1155 /// RRs containing compression pointers in the RDATA part cannot be
1156 /// treated transparently, as the compression pointers are only
1157 /// meaningful within the context of a DNS message. Transparently
1158 /// copying the RDATA into a new DNS message would cause the compression
1159 /// pointers to point at the corresponding location in the new message,
1160 /// which now contains unrelated data. This would cause the compressed
1161 /// name to be corrupted.
1162 ///
1163 /// To avoid such corruption, servers MUST NOT compress domain names
1164 /// embedded in the RDATA of types that are class-specific or not well-
1165 /// known. This requirement was stated in [RFC1123] without defining the
1166 /// term "well-known"; it is hereby specified that only the RR types
1167 /// defined in [RFC1035] are to be considered "well-known".
1168 ///
1169 /// The specifications of a few existing RR types have explicitly allowed
1170 /// compression contrary to this specification: [RFC2163] specified that
1171 /// compression applies to the PX RR, and [RFC2535] allowed compression
1172 /// in SIG RRs and NXT RRs records. Since this specification disallows
1173 /// compression in these cases, it is an update to [RFC2163] (section 4)
1174 /// and [RFC2535] (sections 4.1.7 and 5.2).
1175 ///
1176 /// Receiving servers MUST decompress domain names in RRs of well-known
1177 /// type, and SHOULD also decompress RRs of type RP, AFSDB, RT, SIG, PX,
1178 /// NXT, NAPTR, and SRV (although the current specification of the SRV RR
1179 /// in [RFC2782] prohibits compression, [RFC2052] mandated it, and some
1180 /// servers following that earlier specification are still in use).
1181 ///
1182 /// Future specifications for new RR types that contain domain names
1183 /// within their RDATA MUST NOT allow the use of name compression for
1184 /// those names, and SHOULD explicitly state that the embedded domain
1185 /// names MUST NOT be compressed.
1186 ///
1187 /// As noted in [RFC1123], the owner name of an RR is always eligible for
1188 /// compression.
1189 ///
1190 /// ...
1191 /// As a courtesy to implementors, it is hereby noted that the complete
1192 /// set of such previously published RR types that contain embedded
1193 /// domain names, and whose DNSSEC canonical form therefore involves
1194 /// downcasing according to the DNS rules for character comparisons,
1195 /// consists of the RR types NS, MD, MF, CNAME, SOA, MB, MG, MR, PTR,
1196 /// HINFO, MINFO, MX, HINFO, RP, AFSDB, RT, SIG, PX, NXT, NAPTR, KX, SRV,
1197 /// DNAME, and A6.
1198 /// ...
1199 /// ```
1200 fn emit(&self, encoder: &mut BinEncoder<'_>) -> ProtoResult<()> {
1201 match self {
1202 Self::A(address) => address.emit(encoder),
1203 Self::AAAA(address) => address.emit(encoder),
1204 Self::ANAME(name) => name.emit(encoder),
1205 Self::CAA(caa) => caa.emit(encoder),
1206 Self::CERT(cert) => cert.emit(encoder),
1207 Self::CNAME(cname) => cname.emit(encoder),
1208 Self::NS(ns) => ns.emit(encoder),
1209 Self::PTR(ptr) => ptr.emit(encoder),
1210 Self::CSYNC(csync) => csync.emit(encoder),
1211 Self::HINFO(hinfo) => hinfo.emit(encoder),
1212 Self::HTTPS(https) => https.emit(encoder),
1213 Self::ZERO => Ok(()),
1214 Self::MX(mx) => mx.emit(encoder),
1215 Self::NAPTR(naptr) => naptr.emit(encoder),
1216 Self::NULL(null) => null.emit(encoder),
1217 Self::OPENPGPKEY(openpgpkey) => openpgpkey.emit(encoder),
1218 Self::OPT(opt) => opt.emit(encoder),
1219 Self::SMIMEA(opt) => opt.emit(encoder),
1220 Self::SOA(soa) => soa.emit(encoder),
1221 Self::SRV(srv) => srv.emit(encoder),
1222 Self::SSHFP(sshfp) => sshfp.emit(encoder),
1223 Self::SVCB(svcb) => svcb.emit(encoder),
1224 Self::TLSA(tlsa) => tlsa.emit(encoder),
1225 Self::TSIG(tsig) => tsig.emit(encoder),
1226 Self::TXT(txt) => txt.emit(encoder),
1227 #[cfg(feature = "__dnssec")]
1228 Self::DNSSEC(rdata) => rdata.emit(encoder),
1229 Self::Unknown { rdata, .. } => rdata.emit(encoder),
1230 Self::Update0(_) => Ok(()),
1231 }
1232 }
1233}
1234
1235impl RecordData for RData {
1236 fn try_borrow(data: &RData) -> Option<&Self> {
1237 Some(data)
1238 }
1239
1240 fn record_type(&self) -> RecordType {
1241 self.record_type()
1242 }
1243
1244 fn into_rdata(self) -> RData {
1245 self
1246 }
1247
1248 fn is_update(&self) -> bool {
1249 matches!(self, RData::Update0(_))
1250 }
1251}
1252
1253impl fmt::Display for RData {
1254 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
1255 fn w<D: fmt::Display>(f: &mut fmt::Formatter<'_>, rdata: D) -> Result<(), fmt::Error> {
1256 write!(f, "{rdata}")
1257 }
1258
1259 match self {
1260 Self::A(address) => w(f, address),
1261 Self::AAAA(address) => w(f, address),
1262 Self::ANAME(name) => w(f, name),
1263 Self::CAA(caa) => w(f, caa),
1264 Self::CERT(cert) => w(f, cert),
1265 // to_lowercase for rfc4034 and rfc6840
1266 Self::CNAME(cname) => w(f, cname),
1267 Self::NS(ns) => w(f, ns),
1268 Self::PTR(ptr) => w(f, ptr),
1269 Self::CSYNC(csync) => w(f, csync),
1270 Self::HINFO(hinfo) => w(f, hinfo),
1271 Self::HTTPS(https) => w(f, https),
1272 Self::ZERO => Ok(()),
1273 // to_lowercase for rfc4034 and rfc6840
1274 Self::MX(mx) => w(f, mx),
1275 Self::NAPTR(naptr) => w(f, naptr),
1276 Self::NULL(null) => w(f, null),
1277 Self::OPENPGPKEY(openpgpkey) => w(f, openpgpkey),
1278 // Opt has no display representation
1279 Self::OPT(_) => Err(fmt::Error),
1280 Self::SMIMEA(smimea) => w(f, smimea),
1281 // to_lowercase for rfc4034 and rfc6840
1282 Self::SOA(soa) => w(f, soa),
1283 // to_lowercase for rfc4034 and rfc6840
1284 Self::SRV(srv) => w(f, srv),
1285 Self::SSHFP(sshfp) => w(f, sshfp),
1286 Self::SVCB(svcb) => w(f, svcb),
1287 Self::TLSA(tlsa) => w(f, tlsa),
1288 Self::TSIG(tsig) => w(f, tsig),
1289 Self::TXT(txt) => w(f, txt),
1290 #[cfg(feature = "__dnssec")]
1291 Self::DNSSEC(rdata) => w(f, rdata),
1292 Self::Unknown { rdata, .. } => w(f, rdata),
1293 Self::Update0(_) => w(f, "UPDATE"),
1294 }
1295 }
1296}
1297
1298impl PartialOrd<Self> for RData {
1299 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
1300 Some(self.cmp(other))
1301 }
1302}
1303
1304impl Ord for RData {
1305 // RFC 4034 DNSSEC Resource Records March 2005
1306 //
1307 // 6.3. Canonical RR Ordering within an RRset
1308 //
1309 // For the purposes of DNS security, RRs with the same owner name,
1310 // class, and type are sorted by treating the RDATA portion of the
1311 // canonical form of each RR as a left-justified unsigned octet sequence
1312 // in which the absence of an octet sorts before a zero octet.
1313 //
1314 // [RFC2181] specifies that an RRset is not allowed to contain duplicate
1315 // records (multiple RRs with the same owner name, class, type, and
1316 // RDATA). Therefore, if an implementation detects duplicate RRs when
1317 // putting the RRset in canonical form, it MUST treat this as a protocol
1318 // error. If the implementation chooses to handle this protocol error
1319 // in the spirit of the robustness principle (being liberal in what it
1320 // accepts), it MUST remove all but one of the duplicate RR(s) for the
1321 // purposes of calculating the canonical form of the RRset.
1322 fn cmp(&self, other: &Self) -> Ordering {
1323 // TODO: how about we just store the bytes with the decoded data?
1324 // the decoded data is useful for queries, the encoded data is needed for transfers, signing
1325 // and ordering.
1326 self.to_bytes().cmp(&other.to_bytes())
1327 }
1328}
1329
1330impl From<IpAddr> for RData {
1331 fn from(ip: IpAddr) -> Self {
1332 match ip {
1333 IpAddr::V4(ip) => RData::A(A(ip)),
1334 IpAddr::V6(ip) => RData::AAAA(AAAA(ip)),
1335 }
1336 }
1337}
1338
1339impl From<Ipv4Addr> for RData {
1340 fn from(ip: Ipv4Addr) -> Self {
1341 RData::A(A(ip))
1342 }
1343}
1344
1345impl From<Ipv6Addr> for RData {
1346 fn from(ip: Ipv6Addr) -> Self {
1347 RData::AAAA(AAAA(ip))
1348 }
1349}
1350
1351#[cfg(test)]
1352mod tests {
1353 #![allow(clippy::dbg_macro, clippy::print_stdout)]
1354
1355 use alloc::string::ToString;
1356 use core::str::FromStr;
1357 #[cfg(feature = "std")]
1358 use std::println;
1359
1360 use super::*;
1361 use crate::rr::domain::Name;
1362 use crate::rr::rdata::{MX, SOA, SRV, TXT};
1363 use crate::serialize::binary::bin_tests::test_emit_data_set;
1364
1365 fn get_data() -> Vec<(RData, Vec<u8>)> {
1366 vec![
1367 (
1368 RData::CNAME(CNAME(Name::from_str("www.example.com.").unwrap())),
1369 vec![
1370 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',
1371 b'o', b'm', 0,
1372 ],
1373 ),
1374 (
1375 RData::MX(MX::new(256, Name::from_str("n.").unwrap())),
1376 vec![1, 0, 1, b'n', 0],
1377 ),
1378 (
1379 RData::NS(NS(Name::from_str("www.example.com.").unwrap())),
1380 vec![
1381 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',
1382 b'o', b'm', 0,
1383 ],
1384 ),
1385 (
1386 RData::PTR(PTR(Name::from_str("www.example.com.").unwrap())),
1387 vec![
1388 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',
1389 b'o', b'm', 0,
1390 ],
1391 ),
1392 (
1393 RData::SOA(SOA::new(
1394 Name::from_str("www.example.com.").unwrap(),
1395 Name::from_str("xxx.example.com.").unwrap(),
1396 u32::MAX,
1397 -1,
1398 -1,
1399 -1,
1400 u32::MAX,
1401 )),
1402 vec![
1403 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',
1404 b'o', b'm', 0, 3, b'x', b'x', b'x', 0xC0, 0x04, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
1405 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
1406 0xFF, 0xFF,
1407 ],
1408 ),
1409 (
1410 RData::TXT(TXT::new(vec![
1411 "abcdef".to_string(),
1412 "ghi".to_string(),
1413 "".to_string(),
1414 "j".to_string(),
1415 ])),
1416 vec![
1417 6, b'a', b'b', b'c', b'd', b'e', b'f', 3, b'g', b'h', b'i', 0, 1, b'j',
1418 ],
1419 ),
1420 (RData::A(A::from(Ipv4Addr::UNSPECIFIED)), vec![0, 0, 0, 0]),
1421 (
1422 RData::AAAA(AAAA::from(Ipv6Addr::UNSPECIFIED)),
1423 vec![0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
1424 ),
1425 (
1426 RData::SRV(SRV::new(
1427 1,
1428 2,
1429 3,
1430 Name::from_str("www.example.com.").unwrap(),
1431 )),
1432 vec![
1433 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 3, b'w', b'w', b'w', 7, b'e', b'x', b'a',
1434 b'm', b'p', b'l', b'e', 3, b'c', b'o', b'm', 0,
1435 ],
1436 ),
1437 (
1438 RData::HINFO(HINFO::new("cpu".to_string(), "os".to_string())),
1439 vec![3, b'c', b'p', b'u', 2, b'o', b's'],
1440 ),
1441 ]
1442 }
1443
1444 // TODO this test kinda sucks, shows the problem with not storing the binary parts
1445 #[test]
1446 fn test_order() {
1447 let ordered: Vec<RData> = vec![
1448 RData::A(A::from(Ipv4Addr::UNSPECIFIED)),
1449 RData::AAAA(AAAA::from(Ipv6Addr::UNSPECIFIED)),
1450 RData::SRV(SRV::new(
1451 1,
1452 2,
1453 3,
1454 Name::from_str("www.example.com").unwrap(),
1455 )),
1456 RData::MX(MX::new(256, Name::from_str("n").unwrap())),
1457 RData::CNAME(CNAME(Name::from_str("www.example.com").unwrap())),
1458 RData::PTR(PTR(Name::from_str("www.example.com").unwrap())),
1459 RData::NS(NS(Name::from_str("www.example.com").unwrap())),
1460 RData::SOA(SOA::new(
1461 Name::from_str("www.example.com").unwrap(),
1462 Name::from_str("xxx.example.com").unwrap(),
1463 u32::MAX,
1464 -1,
1465 -1,
1466 -1,
1467 u32::MAX,
1468 )),
1469 RData::TXT(TXT::new(vec![
1470 "abcdef".to_string(),
1471 "ghi".to_string(),
1472 "".to_string(),
1473 "j".to_string(),
1474 ])),
1475 ];
1476 let mut unordered = vec![
1477 RData::CNAME(CNAME(Name::from_str("www.example.com").unwrap())),
1478 RData::MX(MX::new(256, Name::from_str("n").unwrap())),
1479 RData::PTR(PTR(Name::from_str("www.example.com").unwrap())),
1480 RData::NS(NS(Name::from_str("www.example.com").unwrap())),
1481 RData::SOA(SOA::new(
1482 Name::from_str("www.example.com").unwrap(),
1483 Name::from_str("xxx.example.com").unwrap(),
1484 u32::MAX,
1485 -1,
1486 -1,
1487 -1,
1488 u32::MAX,
1489 )),
1490 RData::TXT(TXT::new(vec![
1491 "abcdef".to_string(),
1492 "ghi".to_string(),
1493 "".to_string(),
1494 "j".to_string(),
1495 ])),
1496 RData::A(A::from(Ipv4Addr::UNSPECIFIED)),
1497 RData::AAAA(AAAA::from(Ipv6Addr::UNSPECIFIED)),
1498 RData::SRV(SRV::new(
1499 1,
1500 2,
1501 3,
1502 Name::from_str("www.example.com").unwrap(),
1503 )),
1504 ];
1505
1506 unordered.sort();
1507 assert_eq!(ordered, unordered);
1508 }
1509
1510 #[test]
1511 #[cfg_attr(not(feature = "std"), expect(clippy::unused_enumerate_index))]
1512 fn test_read() {
1513 for (_test_pass, (expect, binary)) in get_data().into_iter().enumerate() {
1514 #[cfg(feature = "std")]
1515 println!("test {_test_pass}: {binary:?}");
1516 let length = binary.len() as u16; // pre exclusive borrow
1517 let mut decoder = BinDecoder::new(&binary);
1518
1519 assert_eq!(
1520 RData::read(
1521 &mut decoder,
1522 record_type_from_rdata(&expect),
1523 Restrict::new(length)
1524 )
1525 .unwrap(),
1526 expect
1527 );
1528 }
1529 }
1530
1531 fn record_type_from_rdata(rdata: &RData) -> RecordType {
1532 match rdata {
1533 RData::A(..) => RecordType::A,
1534 RData::AAAA(..) => RecordType::AAAA,
1535 RData::ANAME(..) => RecordType::ANAME,
1536 RData::CAA(..) => RecordType::CAA,
1537 RData::CERT(..) => RecordType::CERT,
1538 RData::CNAME(..) => RecordType::CNAME,
1539 RData::CSYNC(..) => RecordType::CSYNC,
1540 RData::HINFO(..) => RecordType::HINFO,
1541 RData::HTTPS(..) => RecordType::HTTPS,
1542 RData::MX(..) => RecordType::MX,
1543 RData::NAPTR(..) => RecordType::NAPTR,
1544 RData::NS(..) => RecordType::NS,
1545 RData::NULL(..) => RecordType::NULL,
1546 RData::OPENPGPKEY(..) => RecordType::OPENPGPKEY,
1547 RData::OPT(..) => RecordType::OPT,
1548 RData::PTR(..) => RecordType::PTR,
1549 RData::SMIMEA(..) => RecordType::SMIMEA,
1550 RData::SOA(..) => RecordType::SOA,
1551 RData::SRV(..) => RecordType::SRV,
1552 RData::SSHFP(..) => RecordType::SSHFP,
1553 RData::SVCB(..) => RecordType::SVCB,
1554 RData::TLSA(..) => RecordType::TLSA,
1555 RData::TSIG(..) => RecordType::TSIG,
1556 RData::TXT(..) => RecordType::TXT,
1557 #[cfg(feature = "__dnssec")]
1558 RData::DNSSEC(rdata) => rdata.to_record_type(),
1559 RData::Unknown { code, .. } => *code,
1560 RData::Update0(record_type) => *record_type,
1561 RData::ZERO => RecordType::ZERO,
1562 }
1563 }
1564
1565 #[test]
1566 fn test_write_to() {
1567 test_emit_data_set(get_data(), |e, d| d.emit(e));
1568 }
1569
1570 #[test]
1571 fn test_a() {
1572 let tokens = ["192.168.0.1"];
1573 let name = Name::from_str("example.com.").unwrap();
1574 let record =
1575 RData::from_tokens(RecordType::A, tokens.iter().map(AsRef::as_ref), Some(&name))
1576 .unwrap();
1577
1578 assert_eq!(record, RData::A("192.168.0.1".parse().unwrap()));
1579 }
1580
1581 #[test]
1582 fn test_a_parse() {
1583 let data = "192.168.0.1";
1584 let record = RData::try_from_str(RecordType::A, data).unwrap();
1585
1586 assert_eq!(record, RData::A("192.168.0.1".parse().unwrap()));
1587 }
1588
1589 #[test]
1590 fn test_aaaa() {
1591 let tokens = ["::1"];
1592 let name = Name::from_str("example.com.").unwrap();
1593 let record = RData::from_tokens(
1594 RecordType::AAAA,
1595 tokens.iter().map(AsRef::as_ref),
1596 Some(&name),
1597 )
1598 .unwrap();
1599
1600 assert_eq!(record, RData::AAAA("::1".parse().unwrap()));
1601 }
1602
1603 #[test]
1604 fn test_aaaa_parse() {
1605 let data = "::1";
1606 let record = RData::try_from_str(RecordType::AAAA, data).unwrap();
1607
1608 assert_eq!(record, RData::AAAA("::1".parse().unwrap()));
1609 }
1610
1611 #[test]
1612 fn test_ns_parse() {
1613 let data = "ns.example.com";
1614 let record = RData::try_from_str(RecordType::NS, data).unwrap();
1615
1616 assert_eq!(
1617 record,
1618 RData::NS(NS(Name::from_str("ns.example.com").unwrap()))
1619 );
1620 }
1621
1622 #[test]
1623 fn test_csync() {
1624 let tokens = ["123", "1", "A", "NS"];
1625 let name = Name::from_str("example.com.").unwrap();
1626 let record = RData::from_tokens(
1627 RecordType::CSYNC,
1628 tokens.iter().map(AsRef::as_ref),
1629 Some(&name),
1630 )
1631 .unwrap();
1632
1633 assert_eq!(
1634 record,
1635 RData::CSYNC(CSYNC::new(
1636 123,
1637 true,
1638 false,
1639 [RecordType::A, RecordType::NS]
1640 ))
1641 );
1642 }
1643
1644 #[test]
1645 fn test_csync_parse() {
1646 let data = "123 1 A NS";
1647 let record = RData::try_from_str(RecordType::CSYNC, data).unwrap();
1648
1649 assert_eq!(
1650 record,
1651 RData::CSYNC(CSYNC::new(
1652 123,
1653 true,
1654 false,
1655 [RecordType::A, RecordType::NS]
1656 ))
1657 );
1658 }
1659
1660 #[cfg(feature = "__dnssec")]
1661 #[test]
1662 #[allow(deprecated)]
1663 fn test_ds() {
1664 let tokens = [
1665 "60485",
1666 "5",
1667 "1",
1668 "2BB183AF5F22588179A53B0A",
1669 "98631FAD1A292118",
1670 ];
1671 let name = Name::from_str("dskey.example.com.").unwrap();
1672 let record = RData::from_tokens(
1673 RecordType::DS,
1674 tokens.iter().map(AsRef::as_ref),
1675 Some(&name),
1676 )
1677 .unwrap();
1678
1679 assert_eq!(
1680 record,
1681 RData::DNSSEC(DNSSECRData::DS(DS::new(
1682 60485,
1683 crate::dnssec::Algorithm::RSASHA1,
1684 crate::dnssec::DigestType::SHA1,
1685 vec![
1686 0x2B, 0xB1, 0x83, 0xAF, 0x5F, 0x22, 0x58, 0x81, 0x79, 0xA5, 0x3B, 0x0A, 0x98,
1687 0x63, 0x1F, 0xAD, 0x1A, 0x29, 0x21, 0x18
1688 ]
1689 )))
1690 );
1691 }
1692
1693 #[test]
1694 fn test_any() {
1695 let tokens = ["test"];
1696 let name = Name::from_str("example.com.").unwrap();
1697 let result = RData::from_tokens(
1698 RecordType::ANY,
1699 tokens.iter().map(AsRef::as_ref),
1700 Some(&name),
1701 );
1702
1703 assert!(result.is_err());
1704 }
1705
1706 #[test]
1707 fn test_dynamically_generated() {
1708 let dynamically_generated = vec![
1709 RecordType::DS,
1710 RecordType::CDS,
1711 RecordType::DNSKEY,
1712 RecordType::CDNSKEY,
1713 RecordType::KEY,
1714 RecordType::NSEC,
1715 RecordType::NSEC3,
1716 RecordType::NSEC3PARAM,
1717 RecordType::RRSIG,
1718 ];
1719
1720 let tokens = ["test"];
1721
1722 let name = Name::from_str("example.com.").unwrap();
1723
1724 for record_type in dynamically_generated {
1725 let result =
1726 RData::from_tokens(record_type, tokens.iter().map(AsRef::as_ref), Some(&name));
1727 assert!(result.is_err());
1728 }
1729 }
1730}