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::DNAME => return Err(ParseError::UnsupportedRecordType(record_type)),
1072 RecordType::HINFO => Self::HINFO(HINFO::from_tokens(tokens)?),
1073 RecordType::HTTPS => Self::HTTPS(HTTPS(SVCB::from_tokens(tokens)?)),
1074 RecordType::IXFR => return Err(ParseError::from("parsing IXFR doesn't make sense")),
1075 RecordType::MX => Self::MX(MX::from_tokens(tokens, origin)?),
1076 RecordType::NAPTR => Self::NAPTR(NAPTR::from_tokens(tokens, origin)?),
1077 RecordType::NULL => {
1078 return Err(ParseError::Message(
1079 "parse is not implemented for NULL record",
1080 ));
1081 }
1082 RecordType::NS => Self::NS(NS(Name::from_tokens(tokens, origin)?)),
1083 RecordType::OPENPGPKEY => Self::OPENPGPKEY(OPENPGPKEY::from_tokens(tokens)?),
1084 RecordType::OPT => return Err(ParseError::from("parsing OPT doesn't make sense")),
1085 RecordType::PTR => Self::PTR(PTR(Name::from_tokens(tokens, origin)?)),
1086 RecordType::SMIMEA => Self::SMIMEA(SMIMEA::from_tokens(tokens)?),
1087 RecordType::SOA => Self::SOA(SOA::from_tokens(tokens, origin)?),
1088 RecordType::SRV => Self::SRV(SRV::from_tokens(tokens, origin)?),
1089 RecordType::SSHFP => Self::SSHFP(SSHFP::from_tokens(tokens)?),
1090 RecordType::SVCB => Self::SVCB(SVCB::from_tokens(tokens)?),
1091 RecordType::TLSA => Self::TLSA(TLSA::from_tokens(tokens)?),
1092 RecordType::TXT => Self::TXT(TXT::from_tokens(tokens)?),
1093 RecordType::SIG => return Err(ParseError::from("parsing SIG doesn't make sense")),
1094 RecordType::DNSKEY => {
1095 return Err(ParseError::from("DNSKEY should be dynamically generated"));
1096 }
1097 RecordType::CDNSKEY => {
1098 return Err(ParseError::from("CDNSKEY should be dynamically generated"));
1099 }
1100 RecordType::KEY => return Err(ParseError::from("KEY should be dynamically generated")),
1101 #[cfg(feature = "__dnssec")]
1102 RecordType::DS => Self::DNSSEC(DNSSECRData::DS(DS::from_tokens(tokens)?)),
1103 #[cfg(not(feature = "__dnssec"))]
1104 RecordType::DS => return Err(ParseError::from("DS should be dynamically generated")),
1105 RecordType::CDS => return Err(ParseError::from("CDS should be dynamically generated")),
1106 RecordType::NSEC => {
1107 return Err(ParseError::from("NSEC should be dynamically generated"));
1108 }
1109 RecordType::NSEC3 => {
1110 return Err(ParseError::from("NSEC3 should be dynamically generated"));
1111 }
1112 RecordType::NSEC3PARAM => {
1113 return Err(ParseError::from(
1114 "NSEC3PARAM should be dynamically generated",
1115 ));
1116 }
1117 RecordType::RRSIG => {
1118 return Err(ParseError::from("RRSIG should be dynamically generated"));
1119 }
1120 RecordType::TSIG => return Err(ParseError::from("TSIG is only used during AXFR")),
1121 #[allow(deprecated)]
1122 RecordType::ZERO => Self::ZERO,
1123 r @ RecordType::Unknown(..) => {
1124 // TODO: add a way to associate generic record types to the zone
1125 return Err(ParseError::UnsupportedRecordType(r));
1126 }
1127 };
1128
1129 Ok(rdata)
1130 }
1131}
1132
1133impl BinEncodable for RData {
1134 /// [RFC 4034](https://tools.ietf.org/html/rfc4034#section-6), DNSSEC Resource Records, March 2005
1135 ///
1136 /// ```text
1137 /// 6.2. Canonical RR Form
1138 ///
1139 /// For the purposes of DNS security, the canonical form of an RR is the
1140 /// wire format of the RR where:
1141 ///
1142 /// ...
1143 ///
1144 /// 3. if the type of the RR is NS, MD, MF, CNAME, SOA, MB, MG, MR, PTR,
1145 /// HINFO, MINFO, MX, HINFO, RP, AFSDB, RT, SIG, PX, NXT, NAPTR, KX,
1146 /// SRV, DNAME, A6, RRSIG, or (rfc6840 removes NSEC), all uppercase
1147 /// US-ASCII letters in the DNS names contained within the RDATA are replaced
1148 /// by the corresponding lowercase US-ASCII letters;
1149 /// ```
1150 ///
1151 /// Canonical name form for all non-1035 records:
1152 /// [RFC 3597](https://tools.ietf.org/html/rfc3597)
1153 /// ```text
1154 /// 4. Domain Name Compression
1155 ///
1156 /// RRs containing compression pointers in the RDATA part cannot be
1157 /// treated transparently, as the compression pointers are only
1158 /// meaningful within the context of a DNS message. Transparently
1159 /// copying the RDATA into a new DNS message would cause the compression
1160 /// pointers to point at the corresponding location in the new message,
1161 /// which now contains unrelated data. This would cause the compressed
1162 /// name to be corrupted.
1163 ///
1164 /// To avoid such corruption, servers MUST NOT compress domain names
1165 /// embedded in the RDATA of types that are class-specific or not well-
1166 /// known. This requirement was stated in [RFC1123] without defining the
1167 /// term "well-known"; it is hereby specified that only the RR types
1168 /// defined in [RFC1035] are to be considered "well-known".
1169 ///
1170 /// The specifications of a few existing RR types have explicitly allowed
1171 /// compression contrary to this specification: [RFC2163] specified that
1172 /// compression applies to the PX RR, and [RFC2535] allowed compression
1173 /// in SIG RRs and NXT RRs records. Since this specification disallows
1174 /// compression in these cases, it is an update to [RFC2163] (section 4)
1175 /// and [RFC2535] (sections 4.1.7 and 5.2).
1176 ///
1177 /// Receiving servers MUST decompress domain names in RRs of well-known
1178 /// type, and SHOULD also decompress RRs of type RP, AFSDB, RT, SIG, PX,
1179 /// NXT, NAPTR, and SRV (although the current specification of the SRV RR
1180 /// in [RFC2782] prohibits compression, [RFC2052] mandated it, and some
1181 /// servers following that earlier specification are still in use).
1182 ///
1183 /// Future specifications for new RR types that contain domain names
1184 /// within their RDATA MUST NOT allow the use of name compression for
1185 /// those names, and SHOULD explicitly state that the embedded domain
1186 /// names MUST NOT be compressed.
1187 ///
1188 /// As noted in [RFC1123], the owner name of an RR is always eligible for
1189 /// compression.
1190 ///
1191 /// ...
1192 /// As a courtesy to implementors, it is hereby noted that the complete
1193 /// set of such previously published RR types that contain embedded
1194 /// domain names, and whose DNSSEC canonical form therefore involves
1195 /// downcasing according to the DNS rules for character comparisons,
1196 /// consists of the RR types NS, MD, MF, CNAME, SOA, MB, MG, MR, PTR,
1197 /// HINFO, MINFO, MX, HINFO, RP, AFSDB, RT, SIG, PX, NXT, NAPTR, KX, SRV,
1198 /// DNAME, and A6.
1199 /// ...
1200 /// ```
1201 fn emit(&self, encoder: &mut BinEncoder<'_>) -> ProtoResult<()> {
1202 match self {
1203 Self::A(address) => address.emit(encoder),
1204 Self::AAAA(address) => address.emit(encoder),
1205 Self::ANAME(name) => name.emit(encoder),
1206 Self::CAA(caa) => caa.emit(encoder),
1207 Self::CERT(cert) => cert.emit(encoder),
1208 Self::CNAME(cname) => cname.emit(encoder),
1209 Self::NS(ns) => ns.emit(encoder),
1210 Self::PTR(ptr) => ptr.emit(encoder),
1211 Self::CSYNC(csync) => csync.emit(encoder),
1212 Self::HINFO(hinfo) => hinfo.emit(encoder),
1213 Self::HTTPS(https) => https.emit(encoder),
1214 Self::ZERO => Ok(()),
1215 Self::MX(mx) => mx.emit(encoder),
1216 Self::NAPTR(naptr) => naptr.emit(encoder),
1217 Self::NULL(null) => null.emit(encoder),
1218 Self::OPENPGPKEY(openpgpkey) => openpgpkey.emit(encoder),
1219 Self::OPT(opt) => opt.emit(encoder),
1220 Self::SMIMEA(opt) => opt.emit(encoder),
1221 Self::SOA(soa) => soa.emit(encoder),
1222 Self::SRV(srv) => srv.emit(encoder),
1223 Self::SSHFP(sshfp) => sshfp.emit(encoder),
1224 Self::SVCB(svcb) => svcb.emit(encoder),
1225 Self::TLSA(tlsa) => tlsa.emit(encoder),
1226 Self::TSIG(tsig) => tsig.emit(encoder),
1227 Self::TXT(txt) => txt.emit(encoder),
1228 #[cfg(feature = "__dnssec")]
1229 Self::DNSSEC(rdata) => rdata.emit(encoder),
1230 Self::Unknown { rdata, .. } => rdata.emit(encoder),
1231 Self::Update0(_) => Ok(()),
1232 }
1233 }
1234}
1235
1236impl RecordData for RData {
1237 fn try_borrow(data: &RData) -> Option<&Self> {
1238 Some(data)
1239 }
1240
1241 fn record_type(&self) -> RecordType {
1242 self.record_type()
1243 }
1244
1245 fn into_rdata(self) -> RData {
1246 self
1247 }
1248
1249 fn is_update(&self) -> bool {
1250 matches!(self, RData::Update0(_))
1251 }
1252}
1253
1254impl fmt::Display for RData {
1255 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
1256 fn w<D: fmt::Display>(f: &mut fmt::Formatter<'_>, rdata: D) -> Result<(), fmt::Error> {
1257 write!(f, "{rdata}")
1258 }
1259
1260 match self {
1261 Self::A(address) => w(f, address),
1262 Self::AAAA(address) => w(f, address),
1263 Self::ANAME(name) => w(f, name),
1264 Self::CAA(caa) => w(f, caa),
1265 Self::CERT(cert) => w(f, cert),
1266 // to_lowercase for rfc4034 and rfc6840
1267 Self::CNAME(cname) => w(f, cname),
1268 Self::NS(ns) => w(f, ns),
1269 Self::PTR(ptr) => w(f, ptr),
1270 Self::CSYNC(csync) => w(f, csync),
1271 Self::HINFO(hinfo) => w(f, hinfo),
1272 Self::HTTPS(https) => w(f, https),
1273 Self::ZERO => Ok(()),
1274 // to_lowercase for rfc4034 and rfc6840
1275 Self::MX(mx) => w(f, mx),
1276 Self::NAPTR(naptr) => w(f, naptr),
1277 Self::NULL(null) => w(f, null),
1278 Self::OPENPGPKEY(openpgpkey) => w(f, openpgpkey),
1279 // Opt has no display representation
1280 Self::OPT(_) => Err(fmt::Error),
1281 Self::SMIMEA(smimea) => w(f, smimea),
1282 // to_lowercase for rfc4034 and rfc6840
1283 Self::SOA(soa) => w(f, soa),
1284 // to_lowercase for rfc4034 and rfc6840
1285 Self::SRV(srv) => w(f, srv),
1286 Self::SSHFP(sshfp) => w(f, sshfp),
1287 Self::SVCB(svcb) => w(f, svcb),
1288 Self::TLSA(tlsa) => w(f, tlsa),
1289 Self::TSIG(tsig) => w(f, tsig),
1290 Self::TXT(txt) => w(f, txt),
1291 #[cfg(feature = "__dnssec")]
1292 Self::DNSSEC(rdata) => w(f, rdata),
1293 Self::Unknown { rdata, .. } => w(f, rdata),
1294 Self::Update0(_) => w(f, "UPDATE"),
1295 }
1296 }
1297}
1298
1299impl PartialOrd<Self> for RData {
1300 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
1301 Some(self.cmp(other))
1302 }
1303}
1304
1305impl Ord for RData {
1306 // RFC 4034 DNSSEC Resource Records March 2005
1307 //
1308 // 6.3. Canonical RR Ordering within an RRset
1309 //
1310 // For the purposes of DNS security, RRs with the same owner name,
1311 // class, and type are sorted by treating the RDATA portion of the
1312 // canonical form of each RR as a left-justified unsigned octet sequence
1313 // in which the absence of an octet sorts before a zero octet.
1314 //
1315 // [RFC2181] specifies that an RRset is not allowed to contain duplicate
1316 // records (multiple RRs with the same owner name, class, type, and
1317 // RDATA). Therefore, if an implementation detects duplicate RRs when
1318 // putting the RRset in canonical form, it MUST treat this as a protocol
1319 // error. If the implementation chooses to handle this protocol error
1320 // in the spirit of the robustness principle (being liberal in what it
1321 // accepts), it MUST remove all but one of the duplicate RR(s) for the
1322 // purposes of calculating the canonical form of the RRset.
1323 fn cmp(&self, other: &Self) -> Ordering {
1324 // TODO: how about we just store the bytes with the decoded data?
1325 // the decoded data is useful for queries, the encoded data is needed for transfers, signing
1326 // and ordering.
1327 self.to_bytes().cmp(&other.to_bytes())
1328 }
1329}
1330
1331impl From<IpAddr> for RData {
1332 fn from(ip: IpAddr) -> Self {
1333 match ip {
1334 IpAddr::V4(ip) => RData::A(A(ip)),
1335 IpAddr::V6(ip) => RData::AAAA(AAAA(ip)),
1336 }
1337 }
1338}
1339
1340impl From<Ipv4Addr> for RData {
1341 fn from(ip: Ipv4Addr) -> Self {
1342 RData::A(A(ip))
1343 }
1344}
1345
1346impl From<Ipv6Addr> for RData {
1347 fn from(ip: Ipv6Addr) -> Self {
1348 RData::AAAA(AAAA(ip))
1349 }
1350}
1351
1352#[cfg(test)]
1353mod tests {
1354 #![allow(clippy::dbg_macro, clippy::print_stdout)]
1355
1356 use alloc::string::ToString;
1357 use core::str::FromStr;
1358 #[cfg(feature = "std")]
1359 use std::println;
1360
1361 use super::*;
1362 use crate::rr::domain::Name;
1363 use crate::rr::rdata::{MX, SOA, SRV, TXT};
1364 use crate::serialize::binary::bin_tests::test_emit_data_set;
1365
1366 fn get_data() -> Vec<(RData, Vec<u8>)> {
1367 vec![
1368 (
1369 RData::CNAME(CNAME(Name::from_str("www.example.com.").unwrap())),
1370 vec![
1371 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',
1372 b'o', b'm', 0,
1373 ],
1374 ),
1375 (
1376 RData::MX(MX::new(256, Name::from_str("n.").unwrap())),
1377 vec![1, 0, 1, b'n', 0],
1378 ),
1379 (
1380 RData::NS(NS(Name::from_str("www.example.com.").unwrap())),
1381 vec![
1382 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',
1383 b'o', b'm', 0,
1384 ],
1385 ),
1386 (
1387 RData::PTR(PTR(Name::from_str("www.example.com.").unwrap())),
1388 vec![
1389 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',
1390 b'o', b'm', 0,
1391 ],
1392 ),
1393 (
1394 RData::SOA(SOA::new(
1395 Name::from_str("www.example.com.").unwrap(),
1396 Name::from_str("xxx.example.com.").unwrap(),
1397 u32::MAX,
1398 -1,
1399 -1,
1400 -1,
1401 u32::MAX,
1402 )),
1403 vec![
1404 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',
1405 b'o', b'm', 0, 3, b'x', b'x', b'x', 0xC0, 0x04, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
1406 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
1407 0xFF, 0xFF,
1408 ],
1409 ),
1410 (
1411 RData::TXT(TXT::new(vec![
1412 "abcdef".to_string(),
1413 "ghi".to_string(),
1414 "".to_string(),
1415 "j".to_string(),
1416 ])),
1417 vec![
1418 6, b'a', b'b', b'c', b'd', b'e', b'f', 3, b'g', b'h', b'i', 0, 1, b'j',
1419 ],
1420 ),
1421 (RData::A(A::from(Ipv4Addr::UNSPECIFIED)), vec![0, 0, 0, 0]),
1422 (
1423 RData::AAAA(AAAA::from(Ipv6Addr::UNSPECIFIED)),
1424 vec![0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
1425 ),
1426 (
1427 RData::SRV(SRV::new(
1428 1,
1429 2,
1430 3,
1431 Name::from_str("www.example.com.").unwrap(),
1432 )),
1433 vec![
1434 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 3, b'w', b'w', b'w', 7, b'e', b'x', b'a',
1435 b'm', b'p', b'l', b'e', 3, b'c', b'o', b'm', 0,
1436 ],
1437 ),
1438 (
1439 RData::HINFO(HINFO::new("cpu".to_string(), "os".to_string())),
1440 vec![3, b'c', b'p', b'u', 2, b'o', b's'],
1441 ),
1442 ]
1443 }
1444
1445 // TODO this test kinda sucks, shows the problem with not storing the binary parts
1446 #[test]
1447 fn test_order() {
1448 let ordered: Vec<RData> = vec![
1449 RData::A(A::from(Ipv4Addr::UNSPECIFIED)),
1450 RData::AAAA(AAAA::from(Ipv6Addr::UNSPECIFIED)),
1451 RData::SRV(SRV::new(
1452 1,
1453 2,
1454 3,
1455 Name::from_str("www.example.com").unwrap(),
1456 )),
1457 RData::MX(MX::new(256, Name::from_str("n").unwrap())),
1458 RData::CNAME(CNAME(Name::from_str("www.example.com").unwrap())),
1459 RData::PTR(PTR(Name::from_str("www.example.com").unwrap())),
1460 RData::NS(NS(Name::from_str("www.example.com").unwrap())),
1461 RData::SOA(SOA::new(
1462 Name::from_str("www.example.com").unwrap(),
1463 Name::from_str("xxx.example.com").unwrap(),
1464 u32::MAX,
1465 -1,
1466 -1,
1467 -1,
1468 u32::MAX,
1469 )),
1470 RData::TXT(TXT::new(vec![
1471 "abcdef".to_string(),
1472 "ghi".to_string(),
1473 "".to_string(),
1474 "j".to_string(),
1475 ])),
1476 ];
1477 let mut unordered = vec![
1478 RData::CNAME(CNAME(Name::from_str("www.example.com").unwrap())),
1479 RData::MX(MX::new(256, Name::from_str("n").unwrap())),
1480 RData::PTR(PTR(Name::from_str("www.example.com").unwrap())),
1481 RData::NS(NS(Name::from_str("www.example.com").unwrap())),
1482 RData::SOA(SOA::new(
1483 Name::from_str("www.example.com").unwrap(),
1484 Name::from_str("xxx.example.com").unwrap(),
1485 u32::MAX,
1486 -1,
1487 -1,
1488 -1,
1489 u32::MAX,
1490 )),
1491 RData::TXT(TXT::new(vec![
1492 "abcdef".to_string(),
1493 "ghi".to_string(),
1494 "".to_string(),
1495 "j".to_string(),
1496 ])),
1497 RData::A(A::from(Ipv4Addr::UNSPECIFIED)),
1498 RData::AAAA(AAAA::from(Ipv6Addr::UNSPECIFIED)),
1499 RData::SRV(SRV::new(
1500 1,
1501 2,
1502 3,
1503 Name::from_str("www.example.com").unwrap(),
1504 )),
1505 ];
1506
1507 unordered.sort();
1508 assert_eq!(ordered, unordered);
1509 }
1510
1511 #[test]
1512 #[cfg_attr(not(feature = "std"), expect(clippy::unused_enumerate_index))]
1513 fn test_read() {
1514 for (_test_pass, (expect, binary)) in get_data().into_iter().enumerate() {
1515 #[cfg(feature = "std")]
1516 println!("test {_test_pass}: {binary:?}");
1517 let length = binary.len() as u16; // pre exclusive borrow
1518 let mut decoder = BinDecoder::new(&binary);
1519
1520 assert_eq!(
1521 RData::read(
1522 &mut decoder,
1523 record_type_from_rdata(&expect),
1524 Restrict::new(length)
1525 )
1526 .unwrap(),
1527 expect
1528 );
1529 }
1530 }
1531
1532 fn record_type_from_rdata(rdata: &RData) -> RecordType {
1533 match rdata {
1534 RData::A(..) => RecordType::A,
1535 RData::AAAA(..) => RecordType::AAAA,
1536 RData::ANAME(..) => RecordType::ANAME,
1537 RData::CAA(..) => RecordType::CAA,
1538 RData::CERT(..) => RecordType::CERT,
1539 RData::CNAME(..) => RecordType::CNAME,
1540 RData::CSYNC(..) => RecordType::CSYNC,
1541 RData::HINFO(..) => RecordType::HINFO,
1542 RData::HTTPS(..) => RecordType::HTTPS,
1543 RData::MX(..) => RecordType::MX,
1544 RData::NAPTR(..) => RecordType::NAPTR,
1545 RData::NS(..) => RecordType::NS,
1546 RData::NULL(..) => RecordType::NULL,
1547 RData::OPENPGPKEY(..) => RecordType::OPENPGPKEY,
1548 RData::OPT(..) => RecordType::OPT,
1549 RData::PTR(..) => RecordType::PTR,
1550 RData::SMIMEA(..) => RecordType::SMIMEA,
1551 RData::SOA(..) => RecordType::SOA,
1552 RData::SRV(..) => RecordType::SRV,
1553 RData::SSHFP(..) => RecordType::SSHFP,
1554 RData::SVCB(..) => RecordType::SVCB,
1555 RData::TLSA(..) => RecordType::TLSA,
1556 RData::TSIG(..) => RecordType::TSIG,
1557 RData::TXT(..) => RecordType::TXT,
1558 #[cfg(feature = "__dnssec")]
1559 RData::DNSSEC(rdata) => rdata.to_record_type(),
1560 RData::Unknown { code, .. } => *code,
1561 RData::Update0(record_type) => *record_type,
1562 RData::ZERO => RecordType::ZERO,
1563 }
1564 }
1565
1566 #[test]
1567 fn test_write_to() {
1568 test_emit_data_set(get_data(), |e, d| d.emit(e));
1569 }
1570
1571 #[test]
1572 fn test_a() {
1573 let tokens = ["192.168.0.1"];
1574 let name = Name::from_str("example.com.").unwrap();
1575 let record =
1576 RData::from_tokens(RecordType::A, tokens.iter().map(AsRef::as_ref), Some(&name))
1577 .unwrap();
1578
1579 assert_eq!(record, RData::A("192.168.0.1".parse().unwrap()));
1580 }
1581
1582 #[test]
1583 fn test_a_parse() {
1584 let data = "192.168.0.1";
1585 let record = RData::try_from_str(RecordType::A, data).unwrap();
1586
1587 assert_eq!(record, RData::A("192.168.0.1".parse().unwrap()));
1588 }
1589
1590 #[test]
1591 fn test_aaaa() {
1592 let tokens = ["::1"];
1593 let name = Name::from_str("example.com.").unwrap();
1594 let record = RData::from_tokens(
1595 RecordType::AAAA,
1596 tokens.iter().map(AsRef::as_ref),
1597 Some(&name),
1598 )
1599 .unwrap();
1600
1601 assert_eq!(record, RData::AAAA("::1".parse().unwrap()));
1602 }
1603
1604 #[test]
1605 fn test_aaaa_parse() {
1606 let data = "::1";
1607 let record = RData::try_from_str(RecordType::AAAA, data).unwrap();
1608
1609 assert_eq!(record, RData::AAAA("::1".parse().unwrap()));
1610 }
1611
1612 #[test]
1613 fn test_ns_parse() {
1614 let data = "ns.example.com";
1615 let record = RData::try_from_str(RecordType::NS, data).unwrap();
1616
1617 assert_eq!(
1618 record,
1619 RData::NS(NS(Name::from_str("ns.example.com").unwrap()))
1620 );
1621 }
1622
1623 #[test]
1624 fn test_csync() {
1625 let tokens = ["123", "1", "A", "NS"];
1626 let name = Name::from_str("example.com.").unwrap();
1627 let record = RData::from_tokens(
1628 RecordType::CSYNC,
1629 tokens.iter().map(AsRef::as_ref),
1630 Some(&name),
1631 )
1632 .unwrap();
1633
1634 assert_eq!(
1635 record,
1636 RData::CSYNC(CSYNC::new(
1637 123,
1638 true,
1639 false,
1640 [RecordType::A, RecordType::NS]
1641 ))
1642 );
1643 }
1644
1645 #[test]
1646 fn test_csync_parse() {
1647 let data = "123 1 A NS";
1648 let record = RData::try_from_str(RecordType::CSYNC, data).unwrap();
1649
1650 assert_eq!(
1651 record,
1652 RData::CSYNC(CSYNC::new(
1653 123,
1654 true,
1655 false,
1656 [RecordType::A, RecordType::NS]
1657 ))
1658 );
1659 }
1660
1661 #[cfg(feature = "__dnssec")]
1662 #[test]
1663 #[allow(deprecated)]
1664 fn test_ds() {
1665 let tokens = [
1666 "60485",
1667 "5",
1668 "1",
1669 "2BB183AF5F22588179A53B0A",
1670 "98631FAD1A292118",
1671 ];
1672 let name = Name::from_str("dskey.example.com.").unwrap();
1673 let record = RData::from_tokens(
1674 RecordType::DS,
1675 tokens.iter().map(AsRef::as_ref),
1676 Some(&name),
1677 )
1678 .unwrap();
1679
1680 assert_eq!(
1681 record,
1682 RData::DNSSEC(DNSSECRData::DS(DS::new(
1683 60485,
1684 crate::dnssec::Algorithm::RSASHA1,
1685 crate::dnssec::DigestType::SHA1,
1686 vec![
1687 0x2B, 0xB1, 0x83, 0xAF, 0x5F, 0x22, 0x58, 0x81, 0x79, 0xA5, 0x3B, 0x0A, 0x98,
1688 0x63, 0x1F, 0xAD, 0x1A, 0x29, 0x21, 0x18
1689 ]
1690 )))
1691 );
1692 }
1693
1694 #[test]
1695 fn test_any() {
1696 let tokens = ["test"];
1697 let name = Name::from_str("example.com.").unwrap();
1698 let result = RData::from_tokens(
1699 RecordType::ANY,
1700 tokens.iter().map(AsRef::as_ref),
1701 Some(&name),
1702 );
1703
1704 assert!(result.is_err());
1705 }
1706
1707 #[test]
1708 fn test_dynamically_generated() {
1709 let dynamically_generated = vec![
1710 RecordType::DS,
1711 RecordType::CDS,
1712 RecordType::DNSKEY,
1713 RecordType::CDNSKEY,
1714 RecordType::KEY,
1715 RecordType::NSEC,
1716 RecordType::NSEC3,
1717 RecordType::NSEC3PARAM,
1718 RecordType::RRSIG,
1719 ];
1720
1721 let tokens = ["test"];
1722
1723 let name = Name::from_str("example.com.").unwrap();
1724
1725 for record_type in dynamically_generated {
1726 let result =
1727 RData::from_tokens(record_type, tokens.iter().map(AsRef::as_ref), Some(&name));
1728 assert!(result.is_err());
1729 }
1730 }
1731}