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