1 /* 2 * Copyright (c) 2017, The OpenThread Authors. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 3. Neither the name of the copyright holder nor the 13 * names of its contributors may be used to endorse or promote products 14 * derived from this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 * POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 /** 30 * @file 31 * This file includes definitions for generating and processing DNS headers. 32 */ 33 34 #ifndef DNS_HEADER_HPP_ 35 #define DNS_HEADER_HPP_ 36 37 #include "openthread-core-config.h" 38 39 #include <openthread/dns.h> 40 #include <openthread/dns_client.h> 41 42 #include "common/appender.hpp" 43 #include "common/as_core_type.hpp" 44 #include "common/clearable.hpp" 45 #include "common/encoding.hpp" 46 #include "common/equatable.hpp" 47 #include "common/message.hpp" 48 #include "crypto/ecdsa.hpp" 49 #include "net/ip4_types.hpp" 50 #include "net/ip6_address.hpp" 51 52 namespace ot { 53 54 /** 55 * @namespace ot::Dns 56 * @brief 57 * This namespace includes definitions for DNS. 58 */ 59 namespace Dns { 60 61 /** 62 * @addtogroup core-dns 63 * 64 * @brief 65 * This module includes definitions for DNS. 66 * 67 * @{ 68 */ 69 70 /** 71 * Implements DNS header generation and parsing. 72 */ 73 OT_TOOL_PACKED_BEGIN 74 class Header : public Clearable<Header> 75 { 76 public: 77 /** 78 * Default constructor for DNS Header. 79 */ Header(void)80 Header(void) { Clear(); } 81 82 /** 83 * Returns the Message ID. 84 * 85 * @returns The Message ID value. 86 */ GetMessageId(void) const87 uint16_t GetMessageId(void) const { return BigEndian::HostSwap16(mMessageId); } 88 89 /** 90 * Sets the Message ID. 91 * 92 * @param[in] aMessageId The Message ID value. 93 */ SetMessageId(uint16_t aMessageId)94 void SetMessageId(uint16_t aMessageId) { mMessageId = BigEndian::HostSwap16(aMessageId); } 95 96 /** 97 * Sets the Message ID to a crypto-secure randomly generated number. 98 * 99 * @retval kErrorNone Successfully generated random Message ID. 100 * @retval kErrorFailed Could not generate random Message ID. 101 */ 102 Error SetRandomMessageId(void); 103 104 /** 105 * Defines types of DNS message. 106 */ 107 enum Type : uint8_t 108 { 109 kTypeQuery = 0, 110 kTypeResponse = 1, 111 }; 112 113 /** 114 * Returns the type of the message. 115 * 116 * @returns The type of the message. 117 */ GetType(void) const118 Type GetType(void) const { return static_cast<Type>((mFlags[0] & kQrFlagMask) >> kQrFlagOffset); } 119 120 /** 121 * Sets the type of the message. 122 * 123 * @param[in] aType The type of the message. 124 */ SetType(Type aType)125 void SetType(Type aType) 126 { 127 mFlags[0] &= ~kQrFlagMask; 128 mFlags[0] |= static_cast<uint8_t>(aType) << kQrFlagOffset; 129 } 130 131 /** 132 * Defines types of query. 133 */ 134 enum QueryType : uint8_t 135 { 136 kQueryTypeStandard = 0, 137 kQueryTypeInverse = 1, 138 kQueryTypeStatus = 2, 139 kQueryTypeNotify = 4, 140 kQueryTypeUpdate = 5, 141 kQueryTypeDso = 6, 142 }; 143 144 /** 145 * Returns the type of the query. 146 * 147 * @returns The type of the query. 148 */ GetQueryType(void) const149 QueryType GetQueryType(void) const { return static_cast<QueryType>((mFlags[0] & kOpCodeMask) >> kOpCodeOffset); } 150 151 /** 152 * Sets the type of the query. 153 * 154 * @param[in] aType The type of the query. 155 */ SetQueryType(QueryType aType)156 void SetQueryType(QueryType aType) 157 { 158 mFlags[0] &= ~kOpCodeMask; 159 mFlags[0] |= static_cast<uint8_t>(aType) << kOpCodeOffset; 160 } 161 162 /** 163 * Specifies in response message if the responding name server is an 164 * authority for the domain name in question section. 165 * 166 * @returns True if Authoritative Answer flag (AA) is set in the header, false otherwise. 167 */ IsAuthoritativeAnswerFlagSet(void) const168 bool IsAuthoritativeAnswerFlagSet(void) const { return (mFlags[0] & kAaFlagMask) == kAaFlagMask; } 169 170 /** 171 * Clears the Authoritative Answer flag (AA) in the header. 172 */ ClearAuthoritativeAnswerFlag(void)173 void ClearAuthoritativeAnswerFlag(void) { mFlags[0] &= ~kAaFlagMask; } 174 175 /** 176 * Sets the Authoritative Answer flag (AA) in the header. 177 */ SetAuthoritativeAnswerFlag(void)178 void SetAuthoritativeAnswerFlag(void) { mFlags[0] |= kAaFlagMask; } 179 180 /** 181 * Specifies if message is truncated. 182 * 183 * @returns True if Truncation flag (TC) is set in the header, false otherwise. 184 */ IsTruncationFlagSet(void) const185 bool IsTruncationFlagSet(void) const { return (mFlags[0] & kTcFlagMask) == kTcFlagMask; } 186 187 /** 188 * Clears the Truncation flag (TC) in the header. 189 */ ClearTruncationFlag(void)190 void ClearTruncationFlag(void) { mFlags[0] &= ~kTcFlagMask; } 191 192 /** 193 * Sets the Truncation flag (TC) in the header. 194 */ SetTruncationFlag(void)195 void SetTruncationFlag(void) { mFlags[0] |= kTcFlagMask; } 196 197 /** 198 * Specifies if resolver wants to direct the name server to pursue 199 * the query recursively. 200 * 201 * @returns True if Recursion Desired flag (RD) is set in the header, false otherwise. 202 */ IsRecursionDesiredFlagSet(void) const203 bool IsRecursionDesiredFlagSet(void) const { return (mFlags[0] & kRdFlagMask) == kRdFlagMask; } 204 205 /** 206 * Clears the Recursion Desired flag (RD) in the header. 207 */ ClearRecursionDesiredFlag(void)208 void ClearRecursionDesiredFlag(void) { mFlags[0] &= ~kRdFlagMask; } 209 210 /** 211 * Sets the Recursion Desired flag (RD) in the header. 212 */ SetRecursionDesiredFlag(void)213 void SetRecursionDesiredFlag(void) { mFlags[0] |= kRdFlagMask; } 214 215 /** 216 * Denotes whether recursive query support is available in the name server. 217 * 218 * @returns True if Recursion Available flag (RA) is set in the header, false otherwise. 219 */ IsRecursionAvailableFlagSet(void) const220 bool IsRecursionAvailableFlagSet(void) const { return (mFlags[1] & kRaFlagMask) == kRaFlagMask; } 221 222 /** 223 * Clears the Recursion Available flag (RA) in the header. 224 */ ClearRecursionAvailableFlag(void)225 void ClearRecursionAvailableFlag(void) { mFlags[1] &= ~kRaFlagMask; } 226 227 /** 228 * Sets the Recursion Available flag (RA) in the header. 229 */ SetRecursionAvailableFlag(void)230 void SetRecursionAvailableFlag(void) { mFlags[1] |= kRaFlagMask; } 231 232 /** 233 * Defines response codes. 234 */ 235 enum Response : uint8_t 236 { 237 kResponseSuccess = 0, ///< Success (no error condition). 238 kResponseFormatError = 1, ///< Server unable to interpret request due to format error. 239 kResponseServerFailure = 2, ///< Server encountered an internal failure. 240 kResponseNameError = 3, ///< Name that ought to exist, does not exists. 241 kResponseNotImplemented = 4, ///< Server does not support the query type (OpCode). 242 kResponseRefused = 5, ///< Server refused to perform operation for policy or security reasons. 243 kResponseNameExists = 6, ///< Some name that ought not to exist, does exist. 244 kResponseRecordExists = 7, ///< Some RRset that ought not to exist, does exist. 245 kResponseRecordNotExists = 8, ///< Some RRset that ought to exist, does not exist. 246 kResponseNotAuth = 9, ///< Service is not authoritative for zone. 247 kResponseNotZone = 10, ///< A name is not in the zone. 248 kDsoTypeNotImplemented = 11, ///< DSO TLV TYPE is not implemented. 249 kResponseBadName = 20, ///< Bad name. 250 kResponseBadAlg = 21, ///< Bad algorithm. 251 kResponseBadTruncation = 22, ///< Bad truncation. 252 }; 253 254 /** 255 * Returns the response code. 256 * 257 * @returns The response code from the header. 258 */ GetResponseCode(void) const259 Response GetResponseCode(void) const { return static_cast<Response>((mFlags[1] & kRCodeMask) >> kRCodeOffset); } 260 261 /** 262 * Sets the response code. 263 * 264 * @param[in] aResponse The type of the response. 265 */ SetResponseCode(Response aResponse)266 void SetResponseCode(Response aResponse) 267 { 268 mFlags[1] &= ~kRCodeMask; 269 mFlags[1] |= static_cast<uint8_t>(aResponse) << kRCodeOffset; 270 } 271 272 /** 273 * Converts a Response Code into a related `Error`. 274 * 275 * - kResponseSuccess (0) : Success (no error condition) -> kErrorNone 276 * - kResponseFormatError (1) : Server unable to interpret due to format error -> kErrorParse 277 * - kResponseServerFailure (2) : Server encountered an internal failure -> kErrorFailed 278 * - kResponseNameError (3) : Name that ought to exist, does not exists -> kErrorNotFound 279 * - kResponseNotImplemented (4) : Server does not support the query type (OpCode) -> kErrorNotImplemented 280 * - kResponseRefused (5) : Server refused for policy/security reasons -> kErrorSecurity 281 * - kResponseNameExists (6) : Some name that ought not to exist, does exist -> kErrorDuplicated 282 * - kResponseRecordExists (7) : Some RRset that ought not to exist, does exist -> kErrorDuplicated 283 * - kResponseRecordNotExists (8) : Some RRset that ought to exist, does not exist -> kErrorNotFound 284 * - kResponseNotAuth (9) : Service is not authoritative for zone -> kErrorSecurity 285 * - kResponseNotZone (10) : A name is not in the zone -> kErrorParse 286 * - kDsoTypeNotImplemented (11) : DSO TLV Type is not implemented -> kErrorNotImplemented 287 * - kResponseBadName (20) : Bad name -> kErrorParse 288 * - kResponseBadAlg (21) : Bad algorithm -> kErrorSecurity 289 * - kResponseBadTruncation (22) : Bad truncation -> kErrorParse 290 * - Other error -> kErrorFailed 291 * 292 * @param[in] aResponse The response code to convert. 293 */ 294 static Error ResponseCodeToError(Response aResponse); 295 296 /** 297 * Returns the number of entries in question section. 298 * 299 * @returns The number of entries in question section. 300 */ GetQuestionCount(void) const301 uint16_t GetQuestionCount(void) const { return BigEndian::HostSwap16(mQdCount); } 302 303 /** 304 * Sets the number of entries in question section. 305 * 306 * @param[in] aCount The number of entries in question section. 307 */ SetQuestionCount(uint16_t aCount)308 void SetQuestionCount(uint16_t aCount) { mQdCount = BigEndian::HostSwap16(aCount); } 309 310 /** 311 * Returns the number of entries in answer section. 312 * 313 * @returns The number of entries in answer section. 314 */ GetAnswerCount(void) const315 uint16_t GetAnswerCount(void) const { return BigEndian::HostSwap16(mAnCount); } 316 317 /** 318 * Sets the number of entries in answer section. 319 * 320 * @param[in] aCount The number of entries in answer section. 321 */ SetAnswerCount(uint16_t aCount)322 void SetAnswerCount(uint16_t aCount) { mAnCount = BigEndian::HostSwap16(aCount); } 323 324 /** 325 * Returns the number of entries in authority records section. 326 * 327 * @returns The number of entries in authority records section. 328 */ GetAuthorityRecordCount(void) const329 uint16_t GetAuthorityRecordCount(void) const { return BigEndian::HostSwap16(mNsCount); } 330 331 /** 332 * Sets the number of entries in authority records section. 333 * 334 * @param[in] aCount The number of entries in authority records section. 335 */ SetAuthorityRecordCount(uint16_t aCount)336 void SetAuthorityRecordCount(uint16_t aCount) { mNsCount = BigEndian::HostSwap16(aCount); } 337 338 /** 339 * Returns the number of entries in additional records section. 340 * 341 * @returns The number of entries in additional records section. 342 */ GetAdditionalRecordCount(void) const343 uint16_t GetAdditionalRecordCount(void) const { return BigEndian::HostSwap16(mArCount); } 344 345 /** 346 * Sets the number of entries in additional records section. 347 * 348 * @param[in] aCount The number of entries in additional records section. 349 */ SetAdditionalRecordCount(uint16_t aCount)350 void SetAdditionalRecordCount(uint16_t aCount) { mArCount = BigEndian::HostSwap16(aCount); } 351 352 private: 353 // Protocol Constants (RFC 1035). 354 static constexpr uint8_t kQrFlagOffset = 7; // QR Flag offset. 355 static constexpr uint8_t kQrFlagMask = 0x01 << kQrFlagOffset; // QR Flag mask. 356 static constexpr uint8_t kOpCodeOffset = 3; // OpCode field offset. 357 static constexpr uint8_t kOpCodeMask = 0x0f << kOpCodeOffset; // OpCode field mask. 358 static constexpr uint8_t kAaFlagOffset = 2; // AA Flag offset. 359 static constexpr uint8_t kAaFlagMask = 0x01 << kAaFlagOffset; // AA Flag mask. 360 static constexpr uint8_t kTcFlagOffset = 1; // TC Flag offset. 361 static constexpr uint8_t kTcFlagMask = 0x01 << kTcFlagOffset; // TC Flag mask. 362 static constexpr uint8_t kRdFlagOffset = 0; // RD Flag offset. 363 static constexpr uint8_t kRdFlagMask = 0x01 << kRdFlagOffset; // RD Flag mask. 364 static constexpr uint8_t kRaFlagOffset = 7; // RA Flag offset. 365 static constexpr uint8_t kRaFlagMask = 0x01 << kRaFlagOffset; // RA Flag mask. 366 static constexpr uint8_t kRCodeOffset = 0; // RCODE field offset. 367 static constexpr uint8_t kRCodeMask = 0x0f << kRCodeOffset; // RCODE field mask. 368 369 uint16_t mMessageId; // Message identifier for requester to match up replies to outstanding queries. 370 uint8_t mFlags[2]; // DNS header flags. 371 uint16_t mQdCount; // Number of entries in the question section. 372 uint16_t mAnCount; // Number of entries in the answer section. 373 uint16_t mNsCount; // Number of entries in the authority records section. 374 uint16_t mArCount; // Number of entries in the additional records section. 375 376 } OT_TOOL_PACKED_END; 377 378 /** 379 * Implements DNS Update message header generation and parsing. 380 * 381 * The DNS header specifies record counts for its four sections: Question, Answer, Authority, and Additional. A DNS 382 * Update header uses the same fields, and the same section formats, but the naming and use of these sections differs: 383 * DNS Update header uses Zone, Prerequisite, Update, Additional Data sections. 384 */ 385 OT_TOOL_PACKED_BEGIN 386 class UpdateHeader : public Header 387 { 388 public: 389 /** 390 * Default constructor for DNS Update message header. 391 */ UpdateHeader(void)392 UpdateHeader(void) { SetQueryType(kQueryTypeUpdate); } 393 394 /** 395 * Returns the number of records in Zone section. 396 * 397 * @returns The number of records in Zone section. 398 */ GetZoneRecordCount(void) const399 uint16_t GetZoneRecordCount(void) const { return GetQuestionCount(); } 400 401 /** 402 * Sets the number of records in Zone section. 403 * 404 * @param[in] aCount The number of records in Zone section. 405 */ SetZoneRecordCount(uint16_t aCount)406 void SetZoneRecordCount(uint16_t aCount) { SetQuestionCount(aCount); } 407 408 /** 409 * Returns the number of records in Prerequisite section. 410 * 411 * @returns The number of records in Prerequisite section. 412 */ GetPrerequisiteRecordCount(void) const413 uint16_t GetPrerequisiteRecordCount(void) const { return GetAnswerCount(); } 414 415 /** 416 * Sets the number of records in Prerequisite section. 417 * 418 * @param[in] aCount The number of records in Prerequisite section. 419 */ SetPrerequisiteRecordCount(uint16_t aCount)420 void SetPrerequisiteRecordCount(uint16_t aCount) { SetAnswerCount(aCount); } 421 422 /** 423 * Returns the number of records in Update section. 424 * 425 * @returns The number of records in Update section. 426 */ GetUpdateRecordCount(void) const427 uint16_t GetUpdateRecordCount(void) const { return GetAuthorityRecordCount(); } 428 429 /** 430 * Sets the number of records in Update section. 431 * 432 * @param[in] aCount The number of records in Update section. 433 */ SetUpdateRecordCount(uint16_t aCount)434 void SetUpdateRecordCount(uint16_t aCount) { SetAuthorityRecordCount(aCount); } 435 436 } OT_TOOL_PACKED_END; 437 438 /** 439 * Represents a DNS name and implements helper methods for encoding/decoding of DNS Names. 440 */ 441 class Name : public Clearable<Name> 442 { 443 public: 444 /** 445 * Max size (number of chars) in a name string array (includes null char at the end of string). 446 */ 447 static constexpr uint8_t kMaxNameSize = OT_DNS_MAX_NAME_SIZE; 448 449 /** 450 * Maximum length in a name string (does not include null char at the end of string). 451 */ 452 static constexpr uint8_t kMaxNameLength = kMaxNameSize - 1; 453 454 /** 455 * Max size (number of chars) in a label string array (includes null char at the end of the string). 456 */ 457 static constexpr uint8_t kMaxLabelSize = OT_DNS_MAX_LABEL_SIZE; 458 459 /** 460 * Maximum length in a label string (does not include null char at the end of string). 461 */ 462 static constexpr uint8_t kMaxLabelLength = kMaxLabelSize - 1; 463 464 /** 465 * Dot character separating labels in a name. 466 */ 467 static constexpr char kLabelSeparatorChar = '.'; 468 469 /** 470 * Represents a string buffer (with `kMaxNameSize`) intended to hold a DNS name. 471 */ 472 typedef char Buffer[kMaxNameSize]; 473 474 /** 475 * Represents a string buffer (with `kMaxLabelSize`) intended to hold a DNS label. 476 */ 477 typedef char LabelBuffer[kMaxLabelSize]; 478 479 /** 480 * Represents the name type. 481 */ 482 enum Type : uint8_t 483 { 484 kTypeEmpty, ///< The name is empty (not specified). 485 kTypeCString, ///< The name is given as a C string (dot '.' separated sequence of labels). 486 kTypeMessage, ///< The name is specified from a message at a given offset (encoded in the message). 487 }; 488 489 /** 490 * Initializes the `Name` object as empty (not specified). 491 */ Name(void)492 Name(void) 493 : Name(nullptr, nullptr, 0) 494 { 495 } 496 497 /** 498 * Initializes the `Name` object with a given string. 499 * 500 * @param[in] aString A C string specifying the name (dot '.' separated sequence of labels'). 501 */ Name(const char * aString)502 explicit Name(const char *aString) 503 : Name(aString, nullptr, 0) 504 { 505 } 506 507 /** 508 * Initializes the `Name` object from a message at a given offset. 509 * 510 * @param[in] aMessage The message containing the encoded name. `aMessage.GetOffset()` MUST point to the start of 511 * the DNS header in the message (used to parse compressed name). 512 * @param[in] aOffset The offset in @p aMessage pointing to the start of the name. 513 */ Name(const Message & aMessage,uint16_t aOffset)514 Name(const Message &aMessage, uint16_t aOffset) 515 : Name(nullptr, &aMessage, aOffset) 516 { 517 } 518 519 /** 520 * Indicates whether the name is empty (not specified). 521 * 522 * @returns TRUE if the name is empty, FALSE otherwise. 523 */ IsEmpty(void) const524 bool IsEmpty(void) const { return (mString == nullptr) && (mMessage == nullptr); } 525 526 /** 527 * Indicates whether the name is specified from a C string. 528 * 529 * @returns TRUE if the name is specified from a string, FALSE otherwise. 530 */ IsFromCString(void) const531 bool IsFromCString(void) const { return mString != nullptr; } 532 533 /** 534 * Indicates whether the name is specified from a message. 535 * 536 * @returns TRUE if the name is specified from a message, FALSE otherwise. 537 */ IsFromMessage(void) const538 bool IsFromMessage(void) const { return mMessage != nullptr; } 539 540 /** 541 * Gets the type of `Name` object indicating whether it is empty, specified by a C string or from a 542 * message 543 * 544 * @returns The name type. 545 */ GetFromType(void) const546 Type GetFromType(void) const 547 { 548 return IsFromCString() ? kTypeCString : (IsFromMessage() ? kTypeMessage : kTypeEmpty); 549 } 550 551 /** 552 * Sets the name from a given C string. 553 * 554 * @param[in] aString A C string specifying the name (dot '.' separated sequence of labels). 555 */ Set(const char * aString)556 void Set(const char *aString) 557 { 558 mString = aString; 559 mMessage = nullptr; 560 } 561 562 /** 563 * Sets the name from a message at a given offset. 564 * 565 * @param[in] aMessage The message containing the encoded name. `aMessage.GetOffset()` MUST point to the start of 566 * the DNS header in the message (used to parse compressed name). 567 * @param[in] aOffset The offset in @p aMessage pointing to the start of the name. 568 */ SetFromMessage(const Message & aMessage,uint16_t aOffset)569 void SetFromMessage(const Message &aMessage, uint16_t aOffset) 570 { 571 mString = nullptr; 572 mMessage = &aMessage; 573 mOffset = aOffset; 574 } 575 576 /** 577 * Gets the name as a C string. 578 * 579 * MUST be used only when the type is `kTypeString`. Otherwise its behavior is undefined. 580 * 581 * @returns A pointer to the C string. 582 */ GetAsCString(void) const583 const char *GetAsCString(void) const { return mString; } 584 585 /** 586 * Gets the name message and offset. 587 * 588 * MUST be used only when the type is `kTypeMessage`. Otherwise its behavior is undefined. 589 * 590 * @param[out] aOffset A reference to a variable to output the offset of the start of the name in the message. 591 * 592 * @returns A reference to the message containing the name. 593 */ GetAsMessage(uint16_t & aOffset) const594 const Message &GetAsMessage(uint16_t &aOffset) const 595 { 596 aOffset = mOffset; 597 return *mMessage; 598 } 599 600 /** 601 * Matches the `Name` with a given set of labels and domain name. 602 * 603 * This method allows the caller to specify name components separately, enabling scenarios like comparing "service 604 * instance name" with separate instance label (which can include dot character), service type, and domain strings. 605 * 606 * @p aFirstLabel can be `nullptr` if not needed. But if non-null, it is treated as a single label and can itself 607 * include dot `.` character. 608 * 609 * The @p aLabels MUST NOT be `nullptr` and MUST follow "<label1>.<label2>.<label3>", i.e., a sequence of one or 610 * more labels separated by dot '.' char, and it MUST NOT end with dot `.`. 611 * 612 * @p aDomain MUST NOT be `nullptr` and MUST have at least one label and MUST always end with a dot `.` character. 613 * 614 * If the above conditions are not satisfied, the behavior of this method is undefined. 615 * 616 * @param[in] aFirstLabel A first label to check. Can be `nullptr`. 617 * @param[in] aLabels A string of dot separated labels, MUST NOT end with dot. 618 * @param[in] aDomain Domain name. MUST end with dot. 619 * 620 * @retval TRUE The name matches the given components. 621 * @retval FALSE The name does not match the given components. 622 */ 623 bool Matches(const char *aFirstLabel, const char *aLabels, const char *aDomain) const; 624 625 /** 626 * Encodes and appends the name to a message. 627 * 628 * If the name is empty (not specified), then root "." is appended to @p aMessage. If the name is from a C string 629 * then the string is checked and appended (similar to static `AppendName(const char *aName, Message &)` method). 630 * If the the name is from a message, then it is read from the message and appended to @p aMessage. Note that in 631 * this case independent of whether the name is compressed or not in its original message, the name is appended 632 * as full (uncompressed) in @p aMessage. 633 * 634 * @param[in] aMessage The message to append to. 635 * 636 * @retval kErrorNone Successfully encoded and appended the name to @p aMessage. 637 * @retval kErrorInvalidArgs Name is not valid. 638 * @retval kErrorNoBufs Insufficient available buffers to grow the message. 639 */ 640 Error AppendTo(Message &aMessage) const; 641 642 /** 643 * Encodes and appends a single name label to a message. 644 * 645 * The @p aLabel is assumed to contain a single name label as a C string (null-terminated). Unlike 646 * `AppendMultipleLabels()` which parses the label string and treats it as sequence of multiple (dot-separated) 647 * labels, this method always appends @p aLabel as a single whole label. This allows the label string to even 648 * contain dot '.' character, which, for example, is useful for "Service Instance Names" where <Instance> portion 649 * is a user-friendly name and can contain dot characters. 650 * 651 * @param[in] aLabel The label string to append. MUST NOT be `nullptr`. 652 * @param[in] aMessage The message to append to. 653 * 654 * @retval kErrorNone Successfully encoded and appended the name label to @p aMessage. 655 * @retval kErrorInvalidArgs @p aLabel is not valid (e.g., label length is not within valid range). 656 * @retval kErrorNoBufs Insufficient available buffers to grow the message. 657 */ 658 static Error AppendLabel(const char *aLabel, Message &aMessage); 659 660 /** 661 * Encodes and appends a sequence of name labels to a given message. 662 * 663 * The @p aLabels must follow "<label1>.<label2>.<label3>", i.e., a sequence of labels separated by dot '.' char. 664 * E.g., "_http._tcp", "_http._tcp." (same as previous one), "host-1.test". 665 * 666 * Validates that the @p aLabels is a valid name format, i.e., no empty label, and labels are 667 * `kMaxLabelLength` (63) characters or less. 668 * 669 * @note This method NEVER adds a label terminator (empty label) to the message, even in the case where @p aLabels 670 * ends with a dot character, e.g., "host-1.test." is treated same as "host-1.test". 671 * 672 * @param[in] aLabels A name label string. Can be `nullptr` (then treated as ""). 673 * @param[in] aMessage The message to which to append the encoded name. 674 * 675 * @retval kErrorNone Successfully encoded and appended the name label(s) to @p aMessage. 676 * @retval kErrorInvalidArgs Name label @p aLabels is not valid. 677 * @retval kErrorNoBufs Insufficient available buffers to grow the message. 678 */ 679 static Error AppendMultipleLabels(const char *aLabels, Message &aMessage); 680 681 /** 682 * Appends a name label terminator to a message. 683 * 684 * An encoded name is terminated by an empty label (a zero byte). 685 * 686 * @param[in] aMessage The message to append to. 687 * 688 * @retval kErrorNone Successfully encoded and appended the terminator label to @p aMessage. 689 * @retval kErrorNoBufs Insufficient available buffers to grow the message. 690 */ 691 static Error AppendTerminator(Message &aMessage); 692 693 /** 694 * Appends a pointer type name label to a message. 695 * 696 * Pointer label is used for name compression. It allows an entire name or a list of labels at the end of an 697 * encoded name to be replaced with a pointer to a prior occurrence of the same name within the message. 698 * 699 * @param[in] aOffset The offset from the start of DNS header to use for pointer value. 700 * @param[in] aMessage The message to append to. 701 * 702 * @retval kErrorNone Successfully encoded and appended the pointer label to @p aMessage. 703 * @retval kErrorNoBufs Insufficient available buffers to grow the message. 704 */ 705 static Error AppendPointerLabel(uint16_t aOffset, Message &aMessage); 706 707 /** 708 * Encodes and appends a full name to a message. 709 * 710 * The @p aName must follow "<label1>.<label2>.<label3>", i.e., a sequence of labels separated by dot '.' char. 711 * E.g., "example.com", "example.com." (same as previous one), "local.", "default.service.arpa", "." or "" (root). 712 * 713 * Validates that the @p aName is a valid name format, i.e. no empty labels, and labels are 714 * `kMaxLabelLength` (63) characters or less, and the name is `kMaxLength` (255) characters or less. 715 * 716 * @param[in] aName A name string. Can be `nullptr` (then treated as "." or root). 717 * @param[in] aMessage The message to append to. 718 * 719 * @retval kErrorNone Successfully encoded and appended the name to @p aMessage. 720 * @retval kErrorInvalidArgs Name @p aName is not valid. 721 * @retval kErrorNoBufs Insufficient available buffers to grow the message. 722 */ 723 static Error AppendName(const char *aName, Message &aMessage); 724 725 /** 726 * Parses and skips over a full name in a message. 727 * 728 * @param[in] aMessage The message to parse the name from. `aMessage.GetOffset()` MUST point to 729 * the start of DNS header (this is used to handle compressed names). 730 * @param[in,out] aOffset On input the offset in @p aMessage pointing to the start of the name field. 731 * On exit (when parsed successfully), @p aOffset is updated to point to the byte 732 * after the end of name field. 733 * 734 * @retval kErrorNone Successfully parsed and skipped over name, @p Offset is updated. 735 * @retval kErrorParse Name could not be parsed (invalid format). 736 */ 737 static Error ParseName(const Message &aMessage, uint16_t &aOffset); 738 739 /** 740 * Reads a name label from a message. 741 * 742 * Can be used to read labels one by one in a name. After a successful label read, @p aOffset is 743 * updated to point to the start of the next label. When we reach the end of the name, kErrorNotFound is 744 * returned. This method handles compressed names which use pointer labels. So as the labels in a name are read, 745 * the @p aOffset may jump back in the message and at the end the @p aOffset does not necessarily point to the end 746 * of the original name field. 747 * 748 * Unlike `ReadName()` which requires and verifies that the read label to contain no dot '.' character, this method 749 * allows the read label to include any character. 750 * 751 * @param[in] aMessage The message to read the label from. `aMessage.GetOffset()` MUST point to 752 * the start of DNS header (this is used to handle compressed names). 753 * @param[in,out] aOffset On input, the offset in @p aMessage pointing to the start of the label to read. 754 * On exit, when successfully read, @p aOffset is updated to point to the start of 755 * the next label. 756 * @param[out] aLabelBuffer A pointer to a char array to output the read label as a null-terminated C string. 757 * @param[in,out] aLabelLength On input, the maximum number chars in @p aLabelBuffer array. 758 * On output, when label is successfully read, @p aLabelLength is updated to return 759 * the label's length (number of chars in the label string, excluding the null char). 760 * 761 * @retval kErrorNone Successfully read the label and updated @p aLabelBuffer, @p aLabelLength, and @p aOffset. 762 * @retval kErrorNotFound Reached the end of name and no more label to read. 763 * @retval kErrorParse Name could not be parsed (invalid format). 764 * @retval kErrorNoBufs Label could not fit in @p aLabelLength chars. 765 */ 766 static Error ReadLabel(const Message &aMessage, uint16_t &aOffset, char *aLabelBuffer, uint8_t &aLabelLength); 767 768 /** 769 * Reads a full name from a message. 770 * 771 * On successful read, the read name follows "<label1>.<label2>.<label3>.", i.e., a sequence of labels separated by 772 * dot '.' character. The read name will ALWAYS end with a dot. 773 * 774 * Verifies that the labels after the first label in message do not contain any dot character. If they do, 775 * returns `kErrorParse`. 776 * 777 * @param[in] aMessage The message to read the name from. `aMessage.GetOffset()` MUST point to 778 * the start of DNS header (this is used to handle compressed names). 779 * @param[in,out] aOffset On input, the offset in @p aMessage pointing to the start of the name field. 780 * On exit (when parsed successfully), @p aOffset is updated to point to the byte 781 * after the end of name field. 782 * @param[out] aNameBuffer A pointer to a char array to output the read name as a null-terminated C string. 783 * @param[in,out] aNameBufferSize The maximum number of chars in @p aNameBuffer array. 784 * 785 * @retval kErrorNone Successfully read the name, @p aNameBuffer and @p Offset are updated. 786 * @retval kErrorParse Name could not be parsed (invalid format). 787 * @retval kErrorNoBufs Name could not fit in @p aNameBufferSize chars. 788 */ 789 static Error ReadName(const Message &aMessage, uint16_t &aOffset, char *aNameBuffer, uint16_t aNameBufferSize); 790 791 /** 792 * Reads a full name from a message. 793 * 794 * On successful read, the read name follows "<label1>.<label2>.<label3>.", i.e., a sequence of labels separated by 795 * dot '.' character. The read name will ALWAYS end with a dot. 796 * 797 * Verifies that the labels after the first label in message do not contain any dot character. If they do, 798 * returns `kErrorParse`. 799 * 800 * @tparam kNameBufferSize Size of the string buffer array. 801 * 802 * @param[in] aMessage The message to read the name from. `aMessage.GetOffset()` MUST point to 803 * the start of DNS header (this is used to handle compressed names). 804 * @param[in,out] aOffset On input, the offset in @p aMessage pointing to the start of the name field. 805 * On exit (when parsed successfully), @p aOffset is updated to point to the byte 806 * after the end of name field. 807 * @param[out] aNameBuffer Reference to a name string buffer to output the read name. 808 * 809 * @retval kErrorNone Successfully read the name, @p aNameBuffer and @p Offset are updated. 810 * @retval kErrorParse Name could not be parsed (invalid format). 811 * @retval kErrorNoBufs Name could not fit in @p aNameBuffer. 812 */ 813 template <uint16_t kNameBufferSize> ReadName(const Message & aMessage,uint16_t & aOffset,char (& aNameBuffer)[kNameBufferSize])814 static Error ReadName(const Message &aMessage, uint16_t &aOffset, char (&aNameBuffer)[kNameBufferSize]) 815 { 816 return ReadName(aMessage, aOffset, aNameBuffer, kNameBufferSize); 817 } 818 819 /** 820 * Compares a single name label from a message with a given label string. 821 * 822 * Can be used to compare labels one by one. It checks whether the label read from @p aMessage matches 823 * @p aLabel string (case-insensitive comparison). 824 * 825 * Unlike `CompareName()` which requires the labels in the the name string to contain no dot '.' character, this 826 * method allows @p aLabel to include any character. 827 * 828 * @param[in] aMessage The message to read the label from to compare. `aMessage.GetOffset()` MUST point 829 * to the start of DNS header (this is used to handle compressed names). 830 * @param[in,out] aOffset On input, the offset in @p aMessage pointing to the start of the label to read. 831 * On exit and only when label is successfully read and does match @p aLabel, 832 * @p aOffset is updated to point to the start of the next label. 833 * @param[in] aLabel A pointer to a null terminated string containing the label to compare with. 834 * 835 * @retval kErrorNone The label from @p aMessage matches @p aLabel. @p aOffset is updated. 836 * @retval kErrorNotFound The label from @p aMessage does not match @p aLabel (note that @p aOffset is not 837 * updated in this case). 838 * @retval kErrorParse Name could not be parsed (invalid format). 839 */ 840 static Error CompareLabel(const Message &aMessage, uint16_t &aOffset, const char *aLabel); 841 842 /** 843 * Parses and compares multiple name labels from a message. 844 * 845 * Can be used to read and compare a group of labels from an encoded DNS name in a message with possibly more 846 * labels remaining to read. 847 * 848 * The @p aLabels must follow "<label1>.<label2>.<label3>", i.e., a sequence of labels separated by dot '.' char. 849 * 850 * @param[in] aMessage The message to read the labels from to compare. `aMessage.GetOffset()` MUST point 851 * to the start of DNS header (this is used to handle compressed names). 852 * @param[in,out] aOffset On input, the offset in @p aMessage pointing to the start of the labels to read. 853 * On exit and only when all labels are successfully read and match @p aLabels, 854 * @p aOffset is updated to point to the start of the next label. 855 * @param[in] aLabels A pointer to a null terminated string containing the labels to compare with. 856 * 857 * @retval kErrorNone The labels from @p aMessage matches @p aLabels. @p aOffset is updated. 858 * @retval kErrorNotFound The labels from @p aMessage does not match @p aLabel (note that @p aOffset is not 859 * updated in this case). 860 * @retval kErrorParse Name could not be parsed (invalid format). 861 */ 862 static Error CompareMultipleLabels(const Message &aMessage, uint16_t &aOffset, const char *aLabels); 863 864 /** 865 * Parses and compares a full name from a message with a given name. 866 * 867 * Checks whether the encoded name in a message matches a given name string (using case-insensitive 868 * comparison). It checks the name in the message in place and handles compressed names. If the name read from the 869 * message does not match @p aName, it returns `kErrorNotFound`. `kErrorNone` indicates that the name matches 870 * @p aName. 871 * 872 * The @p aName must follow "<label1>.<label2>.<label3>", i.e., a sequence of labels separated by dot '.' char. 873 * E.g., "example.com", "example.com." (same as previous one), "local.", "default.service.arpa", "." or "" (root). 874 * 875 * @param[in] aMessage The message to read the name from and compare with @p aName. 876 * `aMessage.GetOffset()` MUST point to the start of DNS header (this is used to 877 * handle compressed names). 878 * @param[in,out] aOffset On input, the offset in @p aMessage pointing to the start of the name field. 879 * On exit (when parsed successfully independent of whether the read name matches 880 * @p aName or not), @p aOffset is updated to point to the byte after the end of 881 * the name field. 882 * @param[in] aName A pointer to a null terminated string containing the name to compare with. 883 * 884 * @retval kErrorNone The name from @p aMessage matches @p aName. @p aOffset is updated. 885 * @retval kErrorNotFound The name from @p aMessage does not match @p aName. @p aOffset is updated. 886 * @retval kErrorParse Name could not be parsed (invalid format). 887 * @retval kErrorInvalidArgs The @p aName is not a valid name (e.g. back to back "." chars) 888 */ 889 static Error CompareName(const Message &aMessage, uint16_t &aOffset, const char *aName); 890 891 /** 892 * Parses and compares a full name from a message with a name from another message. 893 * 894 * Checks whether the encoded name in @p aMessage matches the name from @p aMessage2 (using 895 * case-insensitive comparison). It compares the names in both messages in place and handles compressed names. Note 896 * that this method works correctly even when the same message instance is used for both @p aMessage and 897 * @p aMessage2 (e.g., at different offsets). 898 * 899 * Only the name in @p aMessage is fully parsed and checked for parse errors. This method assumes that the name in 900 * @p aMessage2 was previously parsed and validated before calling this method (if there is a parse error in 901 * @p aMessage2, it is treated as a name mismatch with @p aMessage). 902 * 903 * If the name in @p aMessage can be parsed fully (independent of whether the name matches or not with the name 904 * from @p aMessage2), the @p aOffset is updated (note that @p aOffset2 for @p aMessage2 is not changed). 905 * 906 * @param[in] aMessage The message to read the name from and compare. `aMessage.GetOffset()` MUST point 907 * to the start of DNS header (this is used to handle compressed names). 908 * @param[in,out] aOffset On input, the offset in @p aMessage pointing to the start of the name field. 909 * On exit (when parsed successfully independent of whether the read name matches 910 * or not), @p aOffset is updated to point to the byte after the end of the name 911 * field. 912 * @param[in] aMessage2 The second message to read the name from and compare with name from @p aMessage. 913 * `aMessage2.GetOffset()` MUST point to the start of DNS header. 914 * @param[in] aOffset2 The offset in @p aMessage2 pointing to the start of the name field. 915 * 916 * @retval kErrorNone The name from @p aMessage matches the name from @p aMessage2. @p aOffset is updated. 917 * @retval kErrorNotFound The name from @p aMessage does not match the name from @p aMessage2. @p aOffset is 918 * updated. 919 * @retval kErrorParse Name in @p aMessage could not be parsed (invalid format). 920 */ 921 static Error CompareName(const Message &aMessage, uint16_t &aOffset, const Message &aMessage2, uint16_t aOffset2); 922 923 /** 924 * Parses and compares a full name from a message with a given name (using case-insensitive 925 * comparison). 926 * 927 * If @p aName is empty (not specified), then any name in @p aMessage is considered a match to it. 928 * 929 * @param[in] aMessage The message to read the name from and compare. `aMessage.GetOffset()` MUST point 930 * to the start of DNS header (this is used to handle compressed names). 931 * @param[in,out] aOffset On input, the offset in @p aMessage pointing to the start of the name field. 932 * On exit (when parsed successfully independent of whether the read name matches 933 * or not), @p aOffset is updated to point to the byte after the end of the name 934 * field. 935 * @param[in] aName A reference to a name to compare with. 936 * 937 * @retval kErrorNone The name from @p aMessage matches @p aName. @p aOffset is updated. 938 * @retval kErrorNotFound The name from @p aMessage does not match @p aName. @p aOffset is updated. 939 * @retval kErrorParse Name in @p aMessage could not be parsed (invalid format). 940 */ 941 static Error CompareName(const Message &aMessage, uint16_t &aOffset, const Name &aName); 942 943 /** 944 * Extracts label(s) from a name by checking that it contains a given suffix name (e.g., suffix name can be 945 * a domain name) and removing it. 946 * 947 * Both @p aName and @p aSuffixName MUST follow the same style regarding inclusion of trailing dot ('.'). Otherwise 948 * `kErrorParse` is returned. 949 * 950 * The @p aLabels buffer may be the same as @p aName for in-place label extraction. In this case, the 951 * implementation avoids unnecessary character copies. 952 * 953 * @param[in] aName The name to extract labels from. 954 * @param[in] aSuffixName The suffix name (e.g., can be domain name). 955 * @param[out] aLabels Pointer to buffer to copy the extracted labels. 956 * @param[in] aLabelsSize Size of @p aLabels buffer. 957 * 958 * @retval kErrorNone Successfully extracted the labels, @p aLabels is updated. 959 * @retval kErrorParse @p aName does not contain @p aSuffixName. 960 * @retval kErrorNoBufs Could not fit the labels in @p aLabelsSize. 961 */ 962 static Error ExtractLabels(const char *aName, const char *aSuffixName, char *aLabels, uint16_t aLabelsSize); 963 964 /** 965 * Extracts label(s) from a name by checking that it contains a given suffix name (e.g., suffix name can be 966 * a domain name) and removing it. 967 * 968 * Both @p aName and @p aSuffixName MUST follow the same style regarding inclusion of trailing dot ('.'). Otherwise 969 * `kErrorParse` is returned. 970 * 971 * The @p aLabels buffer may be the same as @p aName for in-place label extraction. In this case, the 972 * implementation avoids unnecessary character copies. 973 * 974 * @tparam kLabelsBufferSize Size of the buffer string. 975 * 976 * @param[in] aName The name to extract labels from. 977 * @param[in] aSuffixName The suffix name (e.g., can be domain name). 978 * @param[out] aLabelsBuffer A buffer to copy the extracted labels. 979 * 980 * @retval kErrorNone Successfully extracted the labels, @p aLabels is updated. 981 * @retval kErrorParse @p aName does not contain @p aSuffixName. 982 * @retval kErrorNoBufs Could not fit the labels in @p aLabels. 983 */ 984 template <uint16_t kLabelsBufferSize> ExtractLabels(const char * aName,const char * aSuffixName,char (& aLabels)[kLabelsBufferSize])985 static Error ExtractLabels(const char *aName, const char *aSuffixName, char (&aLabels)[kLabelsBufferSize]) 986 { 987 return ExtractLabels(aName, aSuffixName, aLabels, kLabelsBufferSize); 988 } 989 990 /** 991 * Strips a given suffix name (e.g., a domain name) from a given DNS name string, updating it in place. 992 * 993 * First checks that @p Name ends with the given @p aSuffixName, otherwise `kErrorParse` is returned. 994 * 995 * Both @p aName and @p aSuffixName MUST follow the same style regarding inclusion of trailing dot ('.'). Otherwise 996 * `kErrorParse` is returned. 997 * 998 * @tparam kNameBufferSize The size of name buffer. 999 * 1000 * @param[in] aName The name buffer to strip the @p aSuffixName from. 1001 * @param[in] aSuffixName The suffix name (e.g., can be domain name). 1002 * 1003 * @retval kErrorNone Successfully stripped the suffix name from @p aName. 1004 * @retval kErrorParse @p aName does not contain @p aSuffixName. 1005 */ StripName(char (& aName)[kNameBufferSize],const char * aSuffixName)1006 template <uint16_t kNameBufferSize> static Error StripName(char (&aName)[kNameBufferSize], const char *aSuffixName) 1007 { 1008 return ExtractLabels(aName, aSuffixName, aName, kNameBufferSize); 1009 } 1010 1011 /** 1012 * Tests if a DNS name is a sub-domain of a given domain. 1013 * 1014 * Both @p aName and @p aDomain can end without dot ('.'). 1015 * 1016 * @param[in] aName The dot-separated name. 1017 * @param[in] aDomain The dot-separated domain. 1018 * 1019 * @returns TRUE if the name is a sub-domain of @p aDomain, FALSE if is not. 1020 */ 1021 static bool IsSubDomainOf(const char *aName, const char *aDomain); 1022 1023 /** 1024 * Tests if the two DNS name are the same domain. 1025 * 1026 * Both @p aDomain1 and @p aDomain2 can end without dot ('.'). 1027 * 1028 * @param[in] aDomain1 The dot-separated name. 1029 * @param[in] aDomain2 The dot-separated domain. 1030 * 1031 * @retval TRUE If the two DNS names are the same domain. 1032 * @retval FALSE If the two DNS names are not the same domain. 1033 */ 1034 static bool IsSameDomain(const char *aDomain1, const char *aDomain2); 1035 1036 private: 1037 // The first 2 bits of the encoded label specifies label type. 1038 // 1039 // - Value 00 indicates normal text label (lower 6-bits indicates the label length). 1040 // - Value 11 indicates pointer label type (lower 14-bits indicates the pointer offset). 1041 // - Values 01,10 are reserved (RFC 6891 recommends to not use) 1042 1043 static constexpr uint8_t kLabelTypeMask = 0xc0; // 0b1100_0000 (first two bits) 1044 static constexpr uint8_t kTextLabelType = 0x00; // Text label type (00) 1045 static constexpr uint8_t kPointerLabelType = 0xc0; // Pointer label type - compressed name (11) 1046 1047 static constexpr uint8_t kMaxEncodedLength = 255; ///< Max length of an encoded name. 1048 1049 static constexpr uint16_t kPointerLabelTypeUint16 = 0xc000; // Pointer label type mask (first 2 bits). 1050 static constexpr uint16_t kPointerLabelOffsetMask = 0x3fff; // Mask for offset in a pointer label (lower 14 bits). 1051 1052 static constexpr bool kIsSingleLabel = true; // Used in `LabelIterator::CompareLabel()`. 1053 1054 struct LabelIterator 1055 { 1056 static constexpr uint16_t kUnsetNameEndOffset = 0; // Special value indicating `mNameEndOffset` is not yet set. 1057 LabelIteratorot::Dns::Name::LabelIterator1058 LabelIterator(const Message &aMessage, uint16_t aLabelOffset) 1059 : mMessage(aMessage) 1060 , mNextLabelOffset(aLabelOffset) 1061 , mNameEndOffset(kUnsetNameEndOffset) 1062 , mMinLabelOffset(aLabelOffset) 1063 { 1064 } 1065 IsEndOffsetSetot::Dns::Name::LabelIterator1066 bool IsEndOffsetSet(void) const { return (mNameEndOffset != kUnsetNameEndOffset); } 1067 Error GetNextLabel(void); 1068 Error ReadLabel(char *aLabelBuffer, uint8_t &aLabelLength, bool aAllowDotCharInLabel) const; 1069 bool CompareLabel(const char *&aName, bool aIsSingleLabel) const; 1070 bool CompareLabel(const LabelIterator &aOtherIterator) const; 1071 Error AppendLabel(Message &aMessage) const; 1072 1073 static bool CaseInsensitiveMatch(uint8_t aFirst, uint8_t aSecond); 1074 1075 const Message &mMessage; // Message to read labels from. 1076 uint16_t mLabelStartOffset; // Offset in `mMessage` to the first char of current label text. 1077 uint8_t mLabelLength; // Length of current label (number of chars). 1078 uint16_t mNextLabelOffset; // Offset in `mMessage` to the start of the next label. 1079 uint16_t mNameEndOffset; // Offset in `mMessage` to the byte after the end of domain name field. 1080 uint16_t mMinLabelOffset; // Offset in `mMessage` to the start of the earliest parsed label. 1081 }; 1082 Name(const char * aString,const Message * aMessage,uint16_t aOffset)1083 Name(const char *aString, const Message *aMessage, uint16_t aOffset) 1084 : mString(aString) 1085 , mMessage(aMessage) 1086 , mOffset(aOffset) 1087 { 1088 } 1089 1090 static bool CompareAndSkipLabels(const char *&aNamePtr, const char *aLabels, char aExpectedNextChar); 1091 static Error AppendLabel(const char *aLabel, uint8_t aLength, Message &aMessage); 1092 1093 const char *mString; // String containing the name or `nullptr` if name is not from string. 1094 const Message *mMessage; // Message containing the encoded name, or `nullptr` if `Name` is not from message. 1095 uint16_t mOffset; // Offset in `mMessage` to the start of name (used when name is from `mMessage`). 1096 }; 1097 1098 /** 1099 * Represents a TXT record entry representing a key/value pair (RFC 6763 - section 6.3). 1100 */ 1101 class TxtEntry : public otDnsTxtEntry 1102 { 1103 friend class TxtRecord; 1104 1105 public: 1106 /** 1107 * Minimum length of key string (RFC 6763 - section 6.4). 1108 */ 1109 static constexpr uint8_t kMinKeyLength = OT_DNS_TXT_KEY_MIN_LENGTH; 1110 1111 /** 1112 * Recommended max length of key string (RFC 6763 - section 6.4). 1113 */ 1114 static constexpr uint8_t kMaxKeyLength = OT_DNS_TXT_KEY_MAX_LENGTH; 1115 1116 /** 1117 * Maximum length of TXT key string supported by `Iterator`. 1118 * 1119 * This is selected to be longer than recommended `kMaxKeyLength` to handle cases where longer keys are used. 1120 */ 1121 static constexpr uint8_t kMaxIterKeyLength = OT_DNS_TXT_KEY_ITER_MAX_LENGTH; 1122 1123 /** 1124 * Represents an iterator for TXT record entries (key/value pairs). 1125 */ 1126 class Iterator : public otDnsTxtEntryIterator 1127 { 1128 friend class TxtEntry; 1129 1130 public: 1131 /** 1132 * Initializes a TXT record iterator. 1133 * 1134 * The buffer pointer @p aTxtData and its content MUST persist and remain unchanged while the iterator object 1135 * is being used. 1136 * 1137 * @param[in] aTxtData A pointer to buffer containing the encoded TXT data. 1138 * @param[in] aTxtDataLength The length (number of bytes) of @p aTxtData. 1139 */ 1140 void Init(const uint8_t *aTxtData, uint16_t aTxtDataLength); 1141 1142 /** 1143 * Parses the TXT data from the `Iterator` and gets the next TXT record entry (key/value pair). 1144 * 1145 * The `Iterator` instance MUST be initialized using `Init()` before calling this method and the TXT data 1146 * buffer used to initialize the iterator MUST persist and remain unchanged. 1147 * 1148 * If the parsed key string length is smaller than or equal to `kMaxIterKeyLength` the key string is returned 1149 * in `mKey` in @p aEntry. But if the key is longer, then `mKey` is set to `nullptr` the entire encoded TXT 1150 * entry is returned in `mValue` and `mValueLength`. 1151 * 1152 * @param[out] aEntry A reference to a `TxtEntry` to output the parsed/read entry. 1153 * 1154 * @retval kErrorNone The next entry was parsed successfully. @p aEntry is updated. 1155 * @retval kErrorNotFound No more entries in TXT data. 1156 * @retval kErrorParse The TXT data from `Iterator` is not well-formed. 1157 */ 1158 Error GetNextEntry(TxtEntry &aEntry); 1159 1160 private: 1161 static constexpr uint8_t kIndexTxtLength = 0; 1162 static constexpr uint8_t kIndexTxtPosition = 1; 1163 GetTxtData(void) const1164 const char *GetTxtData(void) const { return reinterpret_cast<const char *>(mPtr); } SetTxtData(const uint8_t * aTxtData)1165 void SetTxtData(const uint8_t *aTxtData) { mPtr = aTxtData; } GetTxtDataLength(void) const1166 uint16_t GetTxtDataLength(void) const { return mData[kIndexTxtLength]; } SetTxtDataLength(uint16_t aLength)1167 void SetTxtDataLength(uint16_t aLength) { mData[kIndexTxtLength] = aLength; } GetTxtDataPosition(void) const1168 uint16_t GetTxtDataPosition(void) const { return mData[kIndexTxtPosition]; } SetTxtDataPosition(uint16_t aValue)1169 void SetTxtDataPosition(uint16_t aValue) { mData[kIndexTxtPosition] = aValue; } IncreaseTxtDataPosition(uint16_t aIncrement)1170 void IncreaseTxtDataPosition(uint16_t aIncrement) { mData[kIndexTxtPosition] += aIncrement; } GetKeyBuffer(void)1171 char *GetKeyBuffer(void) { return mChar; } GetTxtDataEnd(void) const1172 const char *GetTxtDataEnd(void) const { return GetTxtData() + GetTxtDataLength(); } 1173 }; 1174 1175 /** 1176 * This is the default constructor for a `TxtEntry` object. 1177 */ 1178 TxtEntry(void) = default; 1179 1180 /** 1181 * Initializes a `TxtEntry` object. 1182 * 1183 * @param[in] aKey A pointer to the key string. 1184 * @param[in] aValue A pointer to a buffer containing the value. 1185 * @param[in] aValueLength Number of bytes in @p aValue buffer. 1186 */ TxtEntry(const char * aKey,const uint8_t * aValue,uint8_t aValueLength)1187 TxtEntry(const char *aKey, const uint8_t *aValue, uint8_t aValueLength) { Init(aKey, aValue, aValueLength); } 1188 1189 /** 1190 * Initializes a `TxtEntry` object. 1191 * 1192 * @param[in] aKey A pointer to the key string. 1193 * @param[in] aValue A pointer to a buffer containing the value. 1194 * @param[in] aValueLength Number of bytes in @p aValue buffer. 1195 */ Init(const char * aKey,const uint8_t * aValue,uint8_t aValueLength)1196 void Init(const char *aKey, const uint8_t *aValue, uint8_t aValueLength) 1197 { 1198 mKey = aKey; 1199 mValue = aValue; 1200 mValueLength = aValueLength; 1201 } 1202 1203 /** 1204 * Encodes and appends the `TxtEntry` to a message. 1205 * 1206 * @param[in] aMessage The message to append to. 1207 * 1208 * @retval kErrorNone Entry was appended successfully to @p aMessage. 1209 * @retval kErrorInvalidArgs The `TxTEntry` info is not valid. 1210 * @retval kErrorNoBufs Insufficient available buffers to grow the message. 1211 */ 1212 Error AppendTo(Message &aMessage) const; 1213 1214 /** 1215 * Appends an array of `TxtEntry` items to a message. 1216 * 1217 * @param[in] aEntries A pointer to array of `TxtEntry` items. 1218 * @param[in] aNumEntries The number of entries in @p aEntries array. 1219 * @param[in] aMessage The message to append to. 1220 * 1221 * @retval kErrorNone Entries appended successfully to @p aMessage. 1222 * @retval kErrorInvalidArgs The `TxTEntry` info is not valid. 1223 * @retval kErrorNoBufs Insufficient available buffers to grow the message. 1224 */ 1225 static Error AppendEntries(const TxtEntry *aEntries, uint16_t aNumEntries, Message &aMessage); 1226 1227 /** 1228 * Appends an array of `TxtEntry` items to a `MutableData` buffer. 1229 * 1230 * @param[in] aEntries A pointer to array of `TxtEntry` items. 1231 * @param[in] aNumEntries The number of entries in @p aEntries array. 1232 * @param[in] aData The `MutableData` to append in. 1233 * 1234 * @retval kErrorNone Entries appended successfully . 1235 * @retval kErrorInvalidArgs The `TxTEntry` info is not valid. 1236 * @retval kErrorNoBufs Insufficient available buffers. 1237 */ 1238 static Error AppendEntries(const TxtEntry *aEntries, uint16_t aNumEntries, MutableData<kWithUint16Length> &aData); 1239 1240 private: 1241 Error AppendTo(Appender &aAppender) const; 1242 static Error AppendEntries(const TxtEntry *aEntries, uint16_t aNumEntries, Appender &aAppender); 1243 1244 static constexpr uint8_t kMaxKeyValueEncodedSize = 255; 1245 static constexpr char kKeyValueSeparator = '='; 1246 }; 1247 1248 /** 1249 * Implements Resource Record (RR) body format. 1250 */ 1251 OT_TOOL_PACKED_BEGIN 1252 class ResourceRecord 1253 { 1254 friend class OptRecord; 1255 1256 public: 1257 // Resource Record Types. 1258 static constexpr uint16_t kTypeZero = 0; ///< Zero as special indicator for the SIG RR (SIG(0) from RFC 2931). 1259 static constexpr uint16_t kTypeA = 1; ///< Address record (IPv4). 1260 static constexpr uint16_t kTypeSoa = 6; ///< Start of (zone of) authority. 1261 static constexpr uint16_t kTypeCname = 5; ///< CNAME record. 1262 static constexpr uint16_t kTypePtr = 12; ///< PTR record. 1263 static constexpr uint16_t kTypeTxt = 16; ///< TXT record. 1264 static constexpr uint16_t kTypeSig = 24; ///< SIG record. 1265 static constexpr uint16_t kTypeKey = 25; ///< KEY record. 1266 static constexpr uint16_t kTypeAaaa = 28; ///< IPv6 address record. 1267 static constexpr uint16_t kTypeSrv = 33; ///< SRV locator record. 1268 static constexpr uint16_t kTypeOpt = 41; ///< Option record. 1269 static constexpr uint16_t kTypeNsec = 47; ///< NSEC record. 1270 static constexpr uint16_t kTypeAny = 255; ///< ANY record. 1271 1272 // Resource Record Class Codes. 1273 static constexpr uint16_t kClassInternet = 1; ///< Class code Internet (IN). 1274 static constexpr uint16_t kClassNone = 254; ///< Class code None (NONE) - RFC 2136. 1275 static constexpr uint16_t kClassAny = 255; ///< Class code Any (ANY). 1276 1277 /** 1278 * Initializes the resource record by setting its type and class. 1279 * 1280 * Only sets the type and class fields. Other fields (TTL and length) remain unchanged/uninitialized. 1281 * 1282 * @param[in] aType The type of the resource record. 1283 * @param[in] aClass The class of the resource record (default is `kClassInternet`). 1284 */ Init(uint16_t aType,uint16_t aClass=kClassInternet)1285 void Init(uint16_t aType, uint16_t aClass = kClassInternet) 1286 { 1287 SetType(aType); 1288 SetClass(aClass); 1289 } 1290 1291 /** 1292 * Indicates whether the resources records matches a given type and class code. 1293 * 1294 * @param[in] aType The resource record type to compare with. 1295 * @param[in] aClass The resource record class code to compare with (default is `kClassInternet`). 1296 * 1297 * @returns TRUE if the resources records matches @p aType and @p aClass, FALSE otherwise. 1298 */ Matches(uint16_t aType,uint16_t aClass=kClassInternet) const1299 bool Matches(uint16_t aType, uint16_t aClass = kClassInternet) const 1300 { 1301 return (mType == BigEndian::HostSwap16(aType)) && (mClass == BigEndian::HostSwap16(aClass)); 1302 } 1303 1304 /** 1305 * Returns the type of the resource record. 1306 * 1307 * @returns The type of the resource record. 1308 */ GetType(void) const1309 uint16_t GetType(void) const { return BigEndian::HostSwap16(mType); } 1310 1311 /** 1312 * Sets the type of the resource record. 1313 * 1314 * @param[in] aType The type of the resource record. 1315 */ SetType(uint16_t aType)1316 void SetType(uint16_t aType) { mType = BigEndian::HostSwap16(aType); } 1317 1318 /** 1319 * Returns the class of the resource record. 1320 * 1321 * @returns The class of the resource record. 1322 */ GetClass(void) const1323 uint16_t GetClass(void) const { return BigEndian::HostSwap16(mClass); } 1324 1325 /** 1326 * Sets the class of the resource record. 1327 * 1328 * @param[in] aClass The class of the resource record. 1329 */ SetClass(uint16_t aClass)1330 void SetClass(uint16_t aClass) { mClass = BigEndian::HostSwap16(aClass); } 1331 1332 /** 1333 * Returns the time to live field of the resource record. 1334 * 1335 * @returns The time to live field of the resource record. 1336 */ GetTtl(void) const1337 uint32_t GetTtl(void) const { return BigEndian::HostSwap32(mTtl); } 1338 1339 /** 1340 * Sets the time to live field of the resource record. 1341 * 1342 * @param[in] aTtl The time to live field of the resource record. 1343 */ SetTtl(uint32_t aTtl)1344 void SetTtl(uint32_t aTtl) { mTtl = BigEndian::HostSwap32(aTtl); } 1345 1346 /** 1347 * Returns the length of the resource record data. 1348 * 1349 * @returns The length of the resource record data. 1350 */ GetLength(void) const1351 uint16_t GetLength(void) const { return BigEndian::HostSwap16(mLength); } 1352 1353 /** 1354 * Sets the length of the resource record data. 1355 * 1356 * @param[in] aLength The length of the resource record data. 1357 */ SetLength(uint16_t aLength)1358 void SetLength(uint16_t aLength) { mLength = BigEndian::HostSwap16(aLength); } 1359 1360 /** 1361 * Returns the size of (number of bytes) in resource record and its data RDATA section (excluding the 1362 * name field). 1363 * 1364 * @returns Size (number of bytes) of resource record and its data section (excluding the name field) 1365 */ GetSize(void) const1366 uint32_t GetSize(void) const { return sizeof(ResourceRecord) + GetLength(); } 1367 1368 /** 1369 * Parses and skips over a given number of resource records in a message from a given offset. 1370 * 1371 * @param[in] aMessage The message from which to parse/read the resource records. `aMessage.GetOffset()` 1372 * MUST point to the start of DNS header. 1373 * @param[in,out] aOffset On input the offset in @p aMessage pointing to the start of the first record. 1374 * On exit (when parsed successfully), @p aOffset is updated to point to the byte after 1375 * the last parsed record. 1376 * @param[in] aNumRecords Number of resource records to parse. 1377 * 1378 * @retval kErrorNone Parsed records successfully. @p aOffset is updated. 1379 * @retval kErrorParse Could not parse the records from @p aMessage (e.g., ran out of bytes in @p aMessage). 1380 */ 1381 static Error ParseRecords(const Message &aMessage, uint16_t &aOffset, uint16_t aNumRecords); 1382 1383 /** 1384 * Searches in a given message to find the first resource record matching a given record name. 1385 * 1386 * @param[in] aMessage The message in which to search for a matching resource record. 1387 * `aMessage.GetOffset()` MUST point to the start of DNS header. 1388 * @param[in,out] aOffset On input, the offset in @p aMessage pointing to the start of the first record. 1389 * On exit, if a matching record is found, @p aOffset is updated to point to the byte 1390 * after the record name. 1391 * If a matching record could not be found, @p aOffset is updated to point to the byte 1392 * after the last record that was checked. 1393 * @param[in,out] aNumRecords On input, the maximum number of records to check (starting from @p aOffset). 1394 * On exit and if a matching record is found, @p aNumRecords is updated to give the 1395 * number of remaining records after @p aOffset (excluding the matching record). 1396 * @param[in] aName The record name to match against. 1397 * 1398 * @retval kErrorNone A matching record was found. @p aOffset, @p aNumRecords are updated. 1399 * @retval kErrorNotFound A matching record could not be found. @p aOffset and @p aNumRecords are updated. 1400 * @retval kErrorParse Could not parse records from @p aMessage (e.g., ran out of bytes in @p aMessage). 1401 */ 1402 static Error FindRecord(const Message &aMessage, uint16_t &aOffset, uint16_t &aNumRecords, const Name &aName); 1403 1404 /** 1405 * This template static method searches in a message to find the i-th occurrence of resource records of specific 1406 * type with a given record name and if found, reads the record from the message. 1407 * 1408 * Searches in @p aMessage starting from @p aOffset up to maximum of @p aNumRecords, for the 1409 * `(aIndex+1)`th occurrence of a resource record of `RecordType` with record name @p aName. 1410 * 1411 * On success (i.e., when a matching record is found and read from the message), @p aOffset is updated to point 1412 * to after the last byte read from the message and copied into @p aRecord. This allows the caller to read any 1413 * remaining fields in the record data. 1414 * 1415 * @tparam RecordType The resource record type (i.e., a sub-class of `ResourceRecord`). 1416 * 1417 * @param[in] aMessage The message to search within for matching resource records. 1418 * `aMessage.GetOffset()` MUST point to the start of DNS header. 1419 * @param[in,out] aOffset On input, the offset in @p aMessage pointing to the start of the first record. 1420 * On exit and only if a matching record is found, @p aOffset is updated to point to 1421 * the last read byte in the record (allowing caller to read any remaining fields in 1422 * the record data from the message). 1423 * @param[in] aNumRecords The maximum number of records to check (starting from @p aOffset). 1424 * @param[in] aIndex The matching record index to find. @p aIndex value of zero returns the first 1425 * matching record. 1426 * @param[in] aName The record name to match against. 1427 * @param[in] aRecord A reference to a record object to read a matching record into. 1428 * If a matching record is found, `sizeof(RecordType)` bytes from @p aMessage are 1429 * read and copied into @p aRecord. 1430 * 1431 * @retval kErrorNone A matching record was found. @p aOffset is updated. 1432 * @retval kErrorNotFound A matching record could not be found. 1433 * @retval kErrorParse Could not parse records from @p aMessage (e.g., ran out of bytes in @p aMessage). 1434 */ 1435 template <class RecordType> FindRecord(const Message & aMessage,uint16_t & aOffset,uint16_t aNumRecords,uint16_t aIndex,const Name & aName,RecordType & aRecord)1436 static Error FindRecord(const Message &aMessage, 1437 uint16_t &aOffset, 1438 uint16_t aNumRecords, 1439 uint16_t aIndex, 1440 const Name &aName, 1441 RecordType &aRecord) 1442 { 1443 return FindRecord(aMessage, aOffset, aNumRecords, aIndex, aName, RecordType::kType, aRecord, 1444 sizeof(RecordType)); 1445 } 1446 1447 /** 1448 * This template static method tries to read a resource record of a given type from a message. If the record type 1449 * does not matches the type, it skips over the record. 1450 * 1451 * Requires the record name to be already parsed/read from the message. On input, @p aOffset should 1452 * point to the start of the `ResourceRecord` fields (type, class, TTL, data length) in @p aMessage. 1453 * 1454 * Verifies that the record is well-formed in the message. It then reads the record type and compares 1455 * it with `RecordType::kType` and ensures that the record size is at least `sizeof(RecordType)`. If it all matches, 1456 * the record is read into @p aRecord. 1457 * 1458 * On success (i.e., when a matching record is read from the message), the @p aOffset is updated to point to after 1459 * the last byte read from the message and copied into @p aRecord and not necessarily the end of the record. 1460 * Depending on the `RecordType` format, there may still be more data bytes left in the record to be read. For 1461 * example, when reading a SRV record using `SrvRecord` type, @p aOffset would point to after the last field in 1462 * `SrvRecord` which is the start of "target host domain name" field. 1463 * 1464 * @tparam RecordType The resource record type (i.e., a sub-class of `ResourceRecord`). 1465 * 1466 * @param[in] aMessage The message from which to read the record. 1467 * @param[in,out] aOffset On input, the offset in @p aMessage pointing to the byte after the record name. 1468 * On exit, if a matching record is read, @p aOffset is updated to point to the last 1469 * read byte in the record. 1470 * If a matching record could not be read, @p aOffset is updated to point to the byte 1471 * after the entire record (skipping over the record). 1472 * @param[out] aRecord A reference to a record to read a matching record into. 1473 * If a matching record is found, `sizeof(RecordType)` bytes from @p aMessage are 1474 * read and copied into @p aRecord. 1475 * 1476 * @retval kErrorNone A matching record was read successfully. @p aOffset, and @p aRecord are updated. 1477 * @retval kErrorNotFound A matching record could not be found. @p aOffset is updated. 1478 * @retval kErrorParse Could not parse records from @p aMessage (e.g., ran out of bytes in @p aMessage). 1479 */ ReadRecord(const Message & aMessage,uint16_t & aOffset,RecordType & aRecord)1480 template <class RecordType> static Error ReadRecord(const Message &aMessage, uint16_t &aOffset, RecordType &aRecord) 1481 { 1482 return ReadRecord(aMessage, aOffset, RecordType::kType, aRecord, sizeof(RecordType)); 1483 } 1484 1485 protected: 1486 Error ReadName(const Message &aMessage, 1487 uint16_t &aOffset, 1488 uint16_t aStartOffset, 1489 char *aNameBuffer, 1490 uint16_t aNameBufferSize, 1491 bool aSkipRecord) const; 1492 Error SkipRecord(const Message &aMessage, uint16_t &aOffset) const; 1493 1494 private: 1495 static constexpr uint16_t kType = kTypeAny; // This is intended for used by `ReadRecord<RecordType>()` only. 1496 1497 static Error FindRecord(const Message &aMessage, 1498 uint16_t &aOffset, 1499 uint16_t aNumRecords, 1500 uint16_t aIndex, 1501 const Name &aName, 1502 uint16_t aType, 1503 ResourceRecord &aRecord, 1504 uint16_t aMinRecordSize); 1505 1506 static Error ReadRecord(const Message &aMessage, 1507 uint16_t &aOffset, 1508 uint16_t aType, 1509 ResourceRecord &aRecord, 1510 uint16_t aMinRecordSize); 1511 1512 Error CheckRecord(const Message &aMessage, uint16_t aOffset) const; 1513 Error ReadFrom(const Message &aMessage, uint16_t aOffset); 1514 1515 uint16_t mType; // The type of the data in RDATA section. 1516 uint16_t mClass; // The class of the data in RDATA section. 1517 uint32_t mTtl; // Specifies the maximum time that the resource record may be cached. 1518 uint16_t mLength; // The length of RDATA section in bytes. 1519 1520 } OT_TOOL_PACKED_END; 1521 1522 /** 1523 * Implements Resource Record body format of A type. 1524 */ 1525 OT_TOOL_PACKED_BEGIN 1526 class ARecord : public ResourceRecord 1527 { 1528 public: 1529 static constexpr uint16_t kType = kTypeA; ///< The A record type. 1530 1531 /** 1532 * Initializes the A Resource Record by setting its type, class, and length. 1533 * 1534 * Other record fields (TTL, address) remain unchanged/uninitialized. 1535 */ Init(void)1536 void Init(void) 1537 { 1538 ResourceRecord::Init(kTypeA); 1539 SetLength(sizeof(Ip4::Address)); 1540 } 1541 1542 /** 1543 * Sets the IPv4 address of the resource record. 1544 * 1545 * @param[in] aAddress The IPv4 address of the resource record. 1546 */ SetAddress(const Ip4::Address & aAddress)1547 void SetAddress(const Ip4::Address &aAddress) { mAddress = aAddress; } 1548 1549 /** 1550 * Returns the reference to IPv4 address of the resource record. 1551 * 1552 * @returns The reference to IPv4 address of the resource record. 1553 */ GetAddress(void) const1554 const Ip4::Address &GetAddress(void) const { return mAddress; } 1555 1556 private: 1557 Ip4::Address mAddress; // IPv4 Address of A Resource Record. 1558 } OT_TOOL_PACKED_END; 1559 1560 /** 1561 * Implements Resource Record body format of CNAME type. 1562 */ 1563 OT_TOOL_PACKED_BEGIN 1564 class CnameRecord : public ResourceRecord 1565 { 1566 public: 1567 static constexpr uint16_t kType = kTypeCname; ///< The CNAME record type. 1568 1569 /** 1570 * Initializes the CNAME Resource Record by setting its type and class. 1571 * 1572 * Other record fields (TTL, length) remain unchanged/uninitialized. 1573 * 1574 * @param[in] aClass The class of the resource record (default is `kClassInternet`). 1575 */ Init(uint16_t aClass=kClassInternet)1576 void Init(uint16_t aClass = kClassInternet) { ResourceRecord::Init(kTypeCname, aClass); } 1577 1578 /** 1579 * Parses and reads the CNAME alias name from a message. 1580 * 1581 * Also verifies that the CNAME record is well-formed (e.g., the record data length `GetLength()` 1582 * matches the CNAME encoded name). 1583 * 1584 * @param[in] aMessage The message to read from. `aMessage.GetOffset()` MUST point to the start of 1585 * DNS header. 1586 * @param[in,out] aOffset On input, the offset in @p aMessage to start of CNAME name field. 1587 * On exit when successfully read, @p aOffset is updated to point to the byte 1588 * after the entire PTR record (skipping over the record). 1589 * @param[out] aNameBuffer A pointer to a char array to output the read name as a null-terminated C string 1590 * (MUST NOT be `nullptr`). 1591 * @param[in] aNameBufferSize The size of @p aNameBuffer. 1592 * 1593 * @retval kErrorNone The CNAME name was read successfully. @p aOffset and @p aNameBuffer are updated. 1594 * @retval kErrorParse The CNAME record in @p aMessage could not be parsed (invalid format). 1595 * @retval kErrorNoBufs Name could not fit in @p aNameBufferSize chars. 1596 */ ReadCanonicalName(const Message & aMessage,uint16_t & aOffset,char * aNameBuffer,uint16_t aNameBufferSize) const1597 Error ReadCanonicalName(const Message &aMessage, 1598 uint16_t &aOffset, 1599 char *aNameBuffer, 1600 uint16_t aNameBufferSize) const 1601 { 1602 return ResourceRecord::ReadName(aMessage, aOffset, /* aStartOffset */ aOffset - sizeof(CnameRecord), 1603 aNameBuffer, aNameBufferSize, /* aSkipRecord */ true); 1604 } 1605 1606 } OT_TOOL_PACKED_END; 1607 1608 /** 1609 * Implements Resource Record body format of PTR type. 1610 */ 1611 OT_TOOL_PACKED_BEGIN 1612 class PtrRecord : public ResourceRecord 1613 { 1614 public: 1615 static constexpr uint16_t kType = kTypePtr; ///< The PTR record type. 1616 1617 /** 1618 * Initializes the PTR Resource Record by setting its type and class. 1619 * 1620 * Other record fields (TTL, length) remain unchanged/uninitialized. 1621 * 1622 * @param[in] aClass The class of the resource record (default is `kClassInternet`). 1623 */ Init(uint16_t aClass=kClassInternet)1624 void Init(uint16_t aClass = kClassInternet) { ResourceRecord::Init(kTypePtr, aClass); } 1625 1626 /** 1627 * Parses and reads the PTR name from a message. 1628 * 1629 * Also verifies that the PTR record is well-formed (e.g., the record data length `GetLength()` matches 1630 * the PTR encoded name). 1631 * 1632 * @param[in] aMessage The message to read from. `aMessage.GetOffset()` MUST point to the start of 1633 * DNS header. 1634 * @param[in,out] aOffset On input, the offset in @p aMessage to start of PTR name field. 1635 * On exit when successfully read, @p aOffset is updated to point to the byte 1636 * after the entire PTR record (skipping over the record). 1637 * @param[out] aNameBuffer A pointer to a char array to output the read name as a null-terminated C string 1638 * (MUST NOT be `nullptr`). 1639 * @param[in] aNameBufferSize The size of @p aNameBuffer. 1640 * 1641 * @retval kErrorNone The PTR name was read successfully. @p aOffset and @p aNameBuffer are updated. 1642 * @retval kErrorParse The PTR record in @p aMessage could not be parsed (invalid format). 1643 * @retval kErrorNoBufs Name could not fit in @p aNameBufferSize chars. 1644 */ ReadPtrName(const Message & aMessage,uint16_t & aOffset,char * aNameBuffer,uint16_t aNameBufferSize) const1645 Error ReadPtrName(const Message &aMessage, uint16_t &aOffset, char *aNameBuffer, uint16_t aNameBufferSize) const 1646 { 1647 return ResourceRecord::ReadName(aMessage, aOffset, /* aStartOffset */ aOffset - sizeof(PtrRecord), aNameBuffer, 1648 aNameBufferSize, 1649 /* aSkipRecord */ true); 1650 } 1651 1652 /** 1653 * Parses and reads the PTR name from a message. 1654 * 1655 * Also verifies that the PTR record is well-formed (e.g., the record data length `GetLength()` matches 1656 * the PTR encoded name). 1657 * 1658 * Unlike the previous method which reads the entire PTR name into a single char buffer, this method reads the 1659 * first label separately and into a different buffer @p aLabelBuffer and the rest of the name into @p aNameBuffer. 1660 * The @p aNameBuffer can be set to `nullptr` if the caller is only interested in the first label. This method is 1661 * intended for "Service Instance Name" where first label (`<Instance>` portion) can be a user-friendly string and 1662 * can contain dot character. 1663 * 1664 * @param[in] aMessage The message to read from. `aMessage.GetOffset()` MUST point to the start of 1665 * DNS header. 1666 * @param[in,out] aOffset On input, the offset in @p aMessage to the start of PTR name field. 1667 * On exit, when successfully read, @p aOffset is updated to point to the byte 1668 * after the entire PTR record (skipping over the record). 1669 * @param[out] aLabelBuffer A pointer to a char array to output the first label as a null-terminated C 1670 * string (MUST NOT be `nullptr`). 1671 * @param[in] aLabelBufferSize The size of @p aLabelBuffer. 1672 * @param[out] aNameBuffer A pointer to a char array to output the rest of name (after first label). Can 1673 * be `nullptr` if caller is only interested in the first label. 1674 * @param[in] aNameBufferSize The size of @p aNameBuffer. 1675 * 1676 * @retval kErrorNone The PTR name was read successfully. @p aOffset, @aLabelBuffer and @aNameBuffer are updated. 1677 * @retval kErrorParse The PTR record in @p aMessage could not be parsed (invalid format). 1678 * @retval kErrorNoBufs Either label or name could not fit in the related char buffers. 1679 */ 1680 Error ReadPtrName(const Message &aMessage, 1681 uint16_t &aOffset, 1682 char *aLabelBuffer, 1683 uint8_t aLabelBufferSize, 1684 char *aNameBuffer, 1685 uint16_t aNameBufferSize) const; 1686 1687 /** 1688 * Parses and reads the PTR name from a message. 1689 * 1690 * This is a template variation of the previous method with name and label buffer sizes as template parameters. 1691 * 1692 * @tparam kLabelBufferSize The size of label buffer. 1693 * @tparam kNameBufferSize The size of name buffer. 1694 * 1695 * @param[in] aMessage The message to read from. `aMessage.GetOffset()` MUST point to the start of 1696 * DNS header. 1697 * @param[in,out] aOffset On input, the offset in @p aMessage to the start of PTR name field. 1698 * On exit, when successfully read, @p aOffset is updated to point to the byte 1699 * after the entire PTR record (skipping over the record). 1700 * @param[out] aLabelBuffer A char array buffer to output the first label as a null-terminated C string. 1701 * @param[out] aNameBuffer A char array to output the rest of name (after first label). 1702 * 1703 * @retval kErrorNone The PTR name was read successfully. @p aOffset, @aLabelBuffer and @aNameBuffer are updated. 1704 * @retval kErrorParse The PTR record in @p aMessage could not be parsed (invalid format). 1705 * @retval kErrorNoBufs Either label or name could not fit in the related given buffers. 1706 */ 1707 template <uint16_t kLabelBufferSize, uint16_t kNameBufferSize> ReadPtrName(const Message & aMessage,uint16_t & aOffset,char (& aLabelBuffer)[kLabelBufferSize],char (& aNameBuffer)[kNameBufferSize]) const1708 Error ReadPtrName(const Message &aMessage, 1709 uint16_t &aOffset, 1710 char (&aLabelBuffer)[kLabelBufferSize], 1711 char (&aNameBuffer)[kNameBufferSize]) const 1712 { 1713 return ReadPtrName(aMessage, aOffset, aLabelBuffer, kLabelBufferSize, aNameBuffer, kNameBufferSize); 1714 } 1715 1716 } OT_TOOL_PACKED_END; 1717 1718 /** 1719 * Implements Resource Record body format of TXT type. 1720 */ 1721 OT_TOOL_PACKED_BEGIN 1722 class TxtRecord : public ResourceRecord 1723 { 1724 public: 1725 static constexpr uint16_t kType = kTypeTxt; ///< The TXT record type. 1726 1727 /** 1728 * Initializes the TXT Resource Record by setting its type and class. 1729 * 1730 * Other record fields (TTL, length) remain unchanged/uninitialized. 1731 * 1732 * @param[in] aClass The class of the resource record (default is `kClassInternet`). 1733 */ Init(uint16_t aClass=kClassInternet)1734 void Init(uint16_t aClass = kClassInternet) { ResourceRecord::Init(kTypeTxt, aClass); } 1735 1736 /** 1737 * Parses and reads the TXT record data from a message. 1738 * 1739 * Also checks if the TXT data is well-formed by calling `VerifyTxtData()` when it is successfully 1740 * read. 1741 * 1742 * @param[in] aMessage The message to read from. 1743 * @param[in,out] aOffset On input, the offset in @p aMessage to start of TXT record data. 1744 * On exit when successfully read, @p aOffset is updated to point to the byte 1745 * after the entire TXT record (skipping over the record). 1746 * @param[out] aTxtBuffer A pointer to a byte array to output the read TXT data. 1747 * @param[in,out] aTxtBufferSize On input, the size of @p aTxtBuffer (max bytes that can be read). 1748 * On exit, @p aTxtBufferSize gives number of bytes written to @p aTxtBuffer. 1749 * 1750 * @retval kErrorNone The TXT data was read successfully. @p aOffset, @p aTxtBuffer and @p aTxtBufferSize 1751 * are updated. 1752 * @retval kErrorParse The TXT record in @p aMessage could not be parsed (invalid format). 1753 * @retval kErrorNoBufs TXT data could not fit in @p aTxtBufferSize bytes. TXT data is still partially read 1754 * into @p aTxtBuffer up to its size and @p aOffset is updated to skip over the full 1755 * TXT record. 1756 */ 1757 Error ReadTxtData(const Message &aMessage, uint16_t &aOffset, uint8_t *aTxtBuffer, uint16_t &aTxtBufferSize) const; 1758 1759 /** 1760 * Tests if a buffer contains valid encoded TXT data. 1761 * 1762 * @param[in] aTxtData The TXT data buffer. 1763 * @param[in] aTxtLength The length of the TXT data buffer. 1764 * @param[in] aAllowEmpty True if zero-length TXT data is allowed. 1765 * 1766 * @returns TRUE if @p aTxtData contains valid encoded TXT data, FALSE if not. 1767 */ 1768 static bool VerifyTxtData(const uint8_t *aTxtData, uint16_t aTxtLength, bool aAllowEmpty); 1769 1770 } OT_TOOL_PACKED_END; 1771 1772 /** 1773 * Implements Resource Record body format of AAAA type. 1774 */ 1775 OT_TOOL_PACKED_BEGIN 1776 class AaaaRecord : public ResourceRecord 1777 { 1778 public: 1779 static constexpr uint16_t kType = kTypeAaaa; ///< The AAAA record type. 1780 1781 /** 1782 * Initializes the AAAA Resource Record by setting its type, class, and length. 1783 * 1784 * Other record fields (TTL, address) remain unchanged/uninitialized. 1785 */ Init(void)1786 void Init(void) 1787 { 1788 ResourceRecord::Init(kTypeAaaa); 1789 SetLength(sizeof(Ip6::Address)); 1790 } 1791 1792 /** 1793 * Tells whether this is a valid AAAA record. 1794 * 1795 * @returns A boolean indicates whether this is a valid AAAA record. 1796 */ 1797 bool IsValid(void) const; 1798 1799 /** 1800 * Sets the IPv6 address of the resource record. 1801 * 1802 * @param[in] aAddress The IPv6 address of the resource record. 1803 */ SetAddress(const Ip6::Address & aAddress)1804 void SetAddress(const Ip6::Address &aAddress) { mAddress = aAddress; } 1805 1806 /** 1807 * Returns the reference to IPv6 address of the resource record. 1808 * 1809 * @returns The reference to IPv6 address of the resource record. 1810 */ GetAddress(void) const1811 const Ip6::Address &GetAddress(void) const { return mAddress; } 1812 1813 private: 1814 Ip6::Address mAddress; // IPv6 Address of AAAA Resource Record. 1815 } OT_TOOL_PACKED_END; 1816 1817 /** 1818 * Implements Resource Record body format of SRV type (RFC 2782). 1819 */ 1820 OT_TOOL_PACKED_BEGIN 1821 class SrvRecord : public ResourceRecord 1822 { 1823 public: 1824 static constexpr uint16_t kType = kTypeSrv; ///< The SRV record type. 1825 1826 /** 1827 * Initializes the SRV Resource Record by settings its type and class. 1828 * 1829 * Other record fields (TTL, length, propriety, weight, port, ...) remain unchanged/uninitialized. 1830 * 1831 * @param[in] aClass The class of the resource record (default is `kClassInternet`). 1832 */ Init(uint16_t aClass=kClassInternet)1833 void Init(uint16_t aClass = kClassInternet) { ResourceRecord::Init(kTypeSrv, aClass); } 1834 1835 /** 1836 * Returns the SRV record's priority value. 1837 * 1838 * @returns The priority value. 1839 */ GetPriority(void) const1840 uint16_t GetPriority(void) const { return BigEndian::HostSwap16(mPriority); } 1841 1842 /** 1843 * Sets the SRV record's priority value. 1844 * 1845 * @param[in] aPriority The priority value. 1846 */ SetPriority(uint16_t aPriority)1847 void SetPriority(uint16_t aPriority) { mPriority = BigEndian::HostSwap16(aPriority); } 1848 1849 /** 1850 * Returns the SRV record's weight value. 1851 * 1852 * @returns The weight value. 1853 */ GetWeight(void) const1854 uint16_t GetWeight(void) const { return BigEndian::HostSwap16(mWeight); } 1855 1856 /** 1857 * Sets the SRV record's weight value. 1858 * 1859 * @param[in] aWeight The weight value. 1860 */ SetWeight(uint16_t aWeight)1861 void SetWeight(uint16_t aWeight) { mWeight = BigEndian::HostSwap16(aWeight); } 1862 1863 /** 1864 * Returns the SRV record's port number on the target host for this service. 1865 * 1866 * @returns The port number. 1867 */ GetPort(void) const1868 uint16_t GetPort(void) const { return BigEndian::HostSwap16(mPort); } 1869 1870 /** 1871 * Sets the SRV record's port number on the target host for this service. 1872 * 1873 * @param[in] aPort The port number. 1874 */ SetPort(uint16_t aPort)1875 void SetPort(uint16_t aPort) { mPort = BigEndian::HostSwap16(aPort); } 1876 1877 /** 1878 * Parses and reads the SRV target host name from a message. 1879 * 1880 * Also verifies that the SRV record is well-formed (e.g., the record data length `GetLength()` matches 1881 * the SRV encoded name). 1882 * 1883 * @param[in] aMessage The message to read from. `aMessage.GetOffset()` MUST point to the start of 1884 * DNS header. 1885 * @param[in,out] aOffset On input, the offset in @p aMessage to start of target host name field. 1886 * On exit when successfully read, @p aOffset is updated to point to the byte 1887 * after the entire SRV record (skipping over the record). 1888 * @param[out] aNameBuffer A pointer to a char array to output the read name as a null-terminated C string 1889 * (MUST NOT be `nullptr`). 1890 * @param[in] aNameBufferSize The size of @p aNameBuffer. 1891 * 1892 * @retval kErrorNone The host name was read successfully. @p aOffset and @p aNameBuffer are updated. 1893 * @retval kErrorParse The SRV record in @p aMessage could not be parsed (invalid format). 1894 * @retval kErrorNoBufs Name could not fit in @p aNameBufferSize chars. 1895 */ ReadTargetHostName(const Message & aMessage,uint16_t & aOffset,char * aNameBuffer,uint16_t aNameBufferSize) const1896 Error ReadTargetHostName(const Message &aMessage, 1897 uint16_t &aOffset, 1898 char *aNameBuffer, 1899 uint16_t aNameBufferSize) const 1900 { 1901 return ResourceRecord::ReadName(aMessage, aOffset, /* aStartOffset */ aOffset - sizeof(SrvRecord), aNameBuffer, 1902 aNameBufferSize, 1903 /* aSkipRecord */ true); 1904 } 1905 1906 /** 1907 * Parses and reads the SRV target host name from a message. 1908 * 1909 * Also verifies that the SRV record is well-formed (e.g., the record data length `GetLength()` matches 1910 * the SRV encoded name). 1911 * 1912 * @tparam kNameBufferSize Size of the name buffer. 1913 * 1914 * @param[in] aMessage The message to read from. `aMessage.GetOffset()` MUST point to the start of 1915 * DNS header. 1916 * @param[in,out] aOffset On input, the offset in @p aMessage to start of target host name field. 1917 * On exit when successfully read, @p aOffset is updated to point to the byte 1918 * after the entire SRV record (skipping over the record). 1919 * @param[out] aNameBuffer A char array to output the read name as a null-terminated C string 1920 * 1921 * @retval kErrorNone The host name was read successfully. @p aOffset and @p aNameBuffer are updated. 1922 * @retval kErrorParse The SRV record in @p aMessage could not be parsed (invalid format). 1923 * @retval kErrorNoBufs Name could not fit in @p aNameBuffer. 1924 */ 1925 template <uint16_t kNameBufferSize> ReadTargetHostName(const Message & aMessage,uint16_t & aOffset,char (& aNameBuffer)[kNameBufferSize]) const1926 Error ReadTargetHostName(const Message &aMessage, uint16_t &aOffset, char (&aNameBuffer)[kNameBufferSize]) const 1927 { 1928 return ReadTargetHostName(aMessage, aOffset, aNameBuffer, kNameBufferSize); 1929 } 1930 1931 private: 1932 uint16_t mPriority; 1933 uint16_t mWeight; 1934 uint16_t mPort; 1935 // Followed by the target host domain name. 1936 1937 } OT_TOOL_PACKED_END; 1938 1939 /** 1940 * Implements Resource Record body format of KEY type (RFC 2535). 1941 */ 1942 OT_TOOL_PACKED_BEGIN 1943 class KeyRecord : public ResourceRecord 1944 { 1945 public: 1946 static constexpr uint16_t kType = kTypeKey; ///< The KEY record type. 1947 1948 // Protocol field values (RFC 2535 - section 3.1.3). 1949 static constexpr uint8_t kProtocolTls = 1; ///< TLS protocol code. 1950 static constexpr uint8_t kProtocolDnsSec = 3; ///< DNS security protocol code. 1951 1952 // Algorithm field values (RFC 8624 - section 3.1). 1953 static constexpr uint8_t kAlgorithmEcdsaP256Sha256 = 13; ///< ECDSA-P256-SHA256 algorithm. 1954 static constexpr uint8_t kAlgorithmEcdsaP384Sha384 = 14; ///< ECDSA-P384-SHA384 algorithm. 1955 static constexpr uint8_t kAlgorithmEd25519 = 15; ///< ED25519 algorithm. 1956 static constexpr uint8_t kAlgorithmEd448 = 16; ///< ED448 algorithm. 1957 1958 /** 1959 * Type represents the use (or key type) flags (RFC 2535 - section 3.1.2). 1960 */ 1961 enum UseFlags : uint8_t 1962 { 1963 kAuthConfidPermitted = 0x00, ///< Use of the key for authentication and/or confidentiality is permitted. 1964 kAuthPermitted = 0x40, ///< Use of the key is only permitted for authentication. 1965 kConfidPermitted = 0x80, ///< Use of the key is only permitted for confidentiality. 1966 kNoKey = 0xc0, ///< No key value (e.g., can indicate zone is not secure). 1967 }; 1968 1969 /** 1970 * Type represents key owner (or name type) flags (RFC 2535 - section 3.1.2). 1971 */ 1972 enum OwnerFlags : uint8_t 1973 { 1974 kOwnerUser = 0x00, ///< Key is associated with a "user" or "account" at end entity. 1975 kOwnerZone = 0x01, ///< Key is a zone key (used for data origin authentication). 1976 kOwnerNonZone = 0x02, ///< Key is associated with a non-zone "entity". 1977 kOwnerReserved = 0x03, ///< Reserved for future use. 1978 }; 1979 1980 // Constants for flag bits for the "signatory" flags (RFC 2137). 1981 // 1982 // The flags defined are for non-zone (`kOwnerNoneZone`) keys (RFC 2137 - section 3.1.3). 1983 1984 /** 1985 * Key is authorized to attach, detach, and move zones. 1986 */ 1987 static constexpr uint8_t kSignatoryFlagZone = 1 << 3; 1988 1989 /** 1990 * Key is authorized to add and delete RRs even if RRs auth with other key. 1991 */ 1992 static constexpr uint8_t kSignatoryFlagStrong = 1 << 2; 1993 1994 /** 1995 * Key is authorized to add and update RRs for only a single owner name. 1996 */ 1997 static constexpr uint8_t kSignatoryFlagUnique = 1 << 1; 1998 1999 /** 2000 * If the other flags are zero, this is used to indicate it is an update key. 2001 */ 2002 static constexpr uint8_t kSignatoryFlagGeneral = 1 << 0; 2003 2004 /** 2005 * Initializes the KEY Resource Record by setting its type and class. 2006 * 2007 * Other record fields (TTL, length, flags, protocol, algorithm) remain unchanged/uninitialized. 2008 * 2009 * @param[in] aClass The class of the resource record (default is `kClassInternet`). 2010 */ Init(uint16_t aClass=kClassInternet)2011 void Init(uint16_t aClass = kClassInternet) { ResourceRecord::Init(kTypeKey, aClass); } 2012 2013 /** 2014 * Tells whether the KEY record is valid. 2015 * 2016 * @returns TRUE if this is a valid KEY record, FALSE if an invalid KEY record. 2017 */ 2018 bool IsValid(void) const; 2019 2020 /** 2021 * Gets the key use (or key type) flags. 2022 * 2023 * @returns The key use flags. 2024 */ GetUseFlags(void) const2025 UseFlags GetUseFlags(void) const { return static_cast<UseFlags>(mFlags[0] & kUseFlagsMask); } 2026 2027 /** 2028 * Gets the owner (or name type) flags. 2029 * 2030 * @returns The key owner flags. 2031 */ GetOwnerFlags(void) const2032 OwnerFlags GetOwnerFlags(void) const { return static_cast<OwnerFlags>(mFlags[0] & kOwnerFlagsMask); } 2033 2034 /** 2035 * Gets the signatory flags. 2036 * 2037 * @returns The signatory flags. 2038 */ GetSignatoryFlags(void) const2039 uint8_t GetSignatoryFlags(void) const { return (mFlags[1] & kSignatoryFlagsMask); } 2040 2041 /** 2042 * Sets the flags field. 2043 * 2044 * @param[in] aUseFlags The `UseFlags` value. 2045 * @param[in] aOwnerFlags The `OwnerFlags` value. 2046 * @param[in] aSignatoryFlags The signatory flags. 2047 */ SetFlags(UseFlags aUseFlags,OwnerFlags aOwnerFlags,uint8_t aSignatoryFlags)2048 void SetFlags(UseFlags aUseFlags, OwnerFlags aOwnerFlags, uint8_t aSignatoryFlags) 2049 { 2050 mFlags[0] = (static_cast<uint8_t>(aUseFlags) | static_cast<uint8_t>(aOwnerFlags)); 2051 mFlags[1] = (aSignatoryFlags & kSignatoryFlagsMask); 2052 } 2053 2054 /** 2055 * Returns the KEY record's protocol value. 2056 * 2057 * @returns The protocol value. 2058 */ GetProtocol(void) const2059 uint8_t GetProtocol(void) const { return mProtocol; } 2060 2061 /** 2062 * Sets the KEY record's protocol value. 2063 * 2064 * @param[in] aProtocol The protocol value. 2065 */ SetProtocol(uint8_t aProtocol)2066 void SetProtocol(uint8_t aProtocol) { mProtocol = aProtocol; } 2067 2068 /** 2069 * Returns the KEY record's algorithm value. 2070 * 2071 * @returns The algorithm value. 2072 */ GetAlgorithm(void) const2073 uint8_t GetAlgorithm(void) const { return mAlgorithm; } 2074 2075 /** 2076 * Sets the KEY record's algorithm value. 2077 * 2078 * @param[in] aAlgorithm The algorithm value. 2079 */ SetAlgorithm(uint8_t aAlgorithm)2080 void SetAlgorithm(uint8_t aAlgorithm) { mAlgorithm = aAlgorithm; } 2081 2082 private: 2083 static constexpr uint8_t kUseFlagsMask = 0xc0; // top two bits in the first flag byte. 2084 static constexpr uint8_t kOwnerFlagsMask = 0x03; // lowest two bits in the first flag byte. 2085 static constexpr uint8_t kSignatoryFlagsMask = 0x0f; // lower 4 bits in the second flag byte. 2086 2087 // Flags format: 2088 // 2089 // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 2090 // +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ 2091 // | Use | Z | XT| Z | Z | Owner | Z | Z | Z | Z | SIG | 2092 // +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ 2093 // \ / \ / 2094 // ---------- mFlags[0] --------- -------- mFlags[1] ---------- 2095 2096 uint8_t mFlags[2]; 2097 uint8_t mProtocol; 2098 uint8_t mAlgorithm; 2099 // Followed by the public key 2100 2101 } OT_TOOL_PACKED_END; 2102 2103 #if OPENTHREAD_CONFIG_SRP_SERVER_ENABLE 2104 OT_TOOL_PACKED_BEGIN 2105 class Ecdsa256KeyRecord : public KeyRecord, public Clearable<Ecdsa256KeyRecord>, public Equatable<Ecdsa256KeyRecord> 2106 { 2107 public: 2108 /** 2109 * Initializes the KEY Resource Record to ECDSA with curve P-256. 2110 * 2111 * Other record fields (TTL, length, flags, protocol) remain unchanged/uninitialized. 2112 */ 2113 void Init(void); 2114 2115 /** 2116 * Tells whether this is a valid ECDSA DNSKEY with curve P-256. 2117 * 2118 * @returns A boolean that indicates whether this is a valid ECDSA DNSKEY RR with curve P-256. 2119 */ 2120 bool IsValid(void) const; 2121 2122 /** 2123 * Returns the ECDSA P-256 public key. 2124 * 2125 * @returns A reference to the public key. 2126 */ GetKey(void) const2127 const Crypto::Ecdsa::P256::PublicKey &GetKey(void) const { return mKey; } 2128 2129 /** 2130 * Sets the ECDSA P-256 public key. 2131 * 2132 * @param[in] aKey The public key. 2133 */ SetKey(const Crypto::Ecdsa::P256::PublicKey & aKey)2134 void SetKey(const Crypto::Ecdsa::P256::PublicKey &aKey) { mKey = aKey; } 2135 2136 private: 2137 Crypto::Ecdsa::P256::PublicKey mKey; 2138 } OT_TOOL_PACKED_END; 2139 #endif // OPENTHREAD_CONFIG_SRP_SERVER_ENABLE 2140 2141 /** 2142 * Implements Resource Record body format of SIG type (RFC 2535 - section-4.1). 2143 */ 2144 OT_TOOL_PACKED_BEGIN 2145 class SigRecord : public ResourceRecord, public Clearable<SigRecord> 2146 { 2147 public: 2148 static constexpr uint16_t kType = kTypeSig; ///< The SIG record type. 2149 2150 /** 2151 * Initializes the SIG Resource Record by setting its type and class. 2152 * 2153 * Other record fields (TTL, length, ...) remain unchanged/uninitialized. 2154 * 2155 * SIG(0) requires SIG RR to set class field as ANY or `kClassAny` (RFC 2931 - section 3). 2156 * 2157 * @param[in] aClass The class of the resource record. 2158 */ Init(uint16_t aClass)2159 void Init(uint16_t aClass) { ResourceRecord::Init(kTypeSig, aClass); } 2160 2161 /** 2162 * Tells whether the SIG record is valid. 2163 * 2164 * @returns TRUE if this is a valid SIG record, FALSE if not a valid SIG record. 2165 */ 2166 bool IsValid(void) const; 2167 2168 /** 2169 * Returns the SIG record's type-covered value. 2170 * 2171 * @returns The type-covered value. 2172 */ GetTypeCovered(void) const2173 uint16_t GetTypeCovered(void) const { return BigEndian::HostSwap16(mTypeCovered); } 2174 2175 /** 2176 * Sets the SIG record's type-covered value. 2177 * 2178 * @param[in] aTypeCovered The type-covered value. 2179 */ SetTypeCovered(uint8_t aTypeCovered)2180 void SetTypeCovered(uint8_t aTypeCovered) { mTypeCovered = BigEndian::HostSwap16(aTypeCovered); } 2181 2182 /** 2183 * Returns the SIG record's algorithm value. 2184 * 2185 * @returns The algorithm value. 2186 */ GetAlgorithm(void) const2187 uint8_t GetAlgorithm(void) const { return mAlgorithm; } 2188 2189 /** 2190 * Sets the SIG record's algorithm value. 2191 * 2192 * @param[in] aAlgorithm The algorithm value. 2193 */ SetAlgorithm(uint8_t aAlgorithm)2194 void SetAlgorithm(uint8_t aAlgorithm) { mAlgorithm = aAlgorithm; } 2195 2196 /** 2197 * Returns the SIG record's labels-count (number of labels, not counting null label, in the original 2198 * name of the owner). 2199 * 2200 * @returns The labels-count value. 2201 */ GetLabels(void) const2202 uint8_t GetLabels(void) const { return mLabels; } 2203 2204 /** 2205 * Sets the SIG record's labels-count (number of labels, not counting null label, in the original 2206 * name of the owner). 2207 * 2208 * @param[in] aLabels The labels-count value. 2209 */ SetLabels(uint8_t aLabels)2210 void SetLabels(uint8_t aLabels) { mLabels = aLabels; } 2211 2212 /** 2213 * Returns the SIG record's original TTL value. 2214 * 2215 * @returns The original TTL value. 2216 */ GetOriginalTtl(void) const2217 uint32_t GetOriginalTtl(void) const { return BigEndian::HostSwap32(mOriginalTtl); } 2218 2219 /** 2220 * Sets the SIG record's original TTL value. 2221 * 2222 * @param[in] aOriginalTtl The original TTL value. 2223 */ SetOriginalTtl(uint32_t aOriginalTtl)2224 void SetOriginalTtl(uint32_t aOriginalTtl) { mOriginalTtl = BigEndian::HostSwap32(aOriginalTtl); } 2225 2226 /** 2227 * Returns the SIG record's expiration time value. 2228 * 2229 * @returns The expiration time value (seconds since Jan 1, 1970). 2230 */ GetExpiration(void) const2231 uint32_t GetExpiration(void) const { return BigEndian::HostSwap32(mExpiration); } 2232 2233 /** 2234 * Sets the SIG record's expiration time value. 2235 * 2236 * @param[in] aExpiration The expiration time value (seconds since Jan 1, 1970). 2237 */ SetExpiration(uint32_t aExpiration)2238 void SetExpiration(uint32_t aExpiration) { mExpiration = BigEndian::HostSwap32(aExpiration); } 2239 2240 /** 2241 * Returns the SIG record's inception time value. 2242 * 2243 * @returns The inception time value (seconds since Jan 1, 1970). 2244 */ GetInception(void) const2245 uint32_t GetInception(void) const { return BigEndian::HostSwap32(mInception); } 2246 2247 /** 2248 * Sets the SIG record's inception time value. 2249 * 2250 * @param[in] aInception The inception time value (seconds since Jan 1, 1970). 2251 */ SetInception(uint32_t aInception)2252 void SetInception(uint32_t aInception) { mInception = BigEndian::HostSwap32(aInception); } 2253 2254 /** 2255 * Returns the SIG record's key tag value. 2256 * 2257 * @returns The key tag value. 2258 */ GetKeyTag(void) const2259 uint16_t GetKeyTag(void) const { return BigEndian::HostSwap16(mKeyTag); } 2260 2261 /** 2262 * Sets the SIG record's key tag value. 2263 * 2264 * @param[in] aKeyTag The key tag value. 2265 */ SetKeyTag(uint16_t aKeyTag)2266 void SetKeyTag(uint16_t aKeyTag) { mKeyTag = BigEndian::HostSwap16(aKeyTag); } 2267 2268 /** 2269 * Returns a pointer to the start of the record data fields. 2270 * 2271 * @returns A pointer to the start of the record data fields. 2272 */ GetRecordData(void) const2273 const uint8_t *GetRecordData(void) const { return reinterpret_cast<const uint8_t *>(&mTypeCovered); } 2274 2275 /** 2276 * Parses and reads the SIG signer name from a message. 2277 * 2278 * @param[in] aMessage The message to read from. `aMessage.GetOffset()` MUST point to the start of DNS 2279 * header. 2280 * @param[in,out] aOffset On input, the offset in @p aMessage to start of signer name field. 2281 * On exit when successfully read, @p aOffset is updated to point to the byte 2282 * after the name field (i.e., start of signature field). 2283 * @param[out] aNameBuffer A pointer to a char array to output the read name as a null-terminated C string 2284 * (MUST NOT be `nullptr`). 2285 * @param[in] aNameBufferSize The size of @p aNameBuffer. 2286 * 2287 * @retval kErrorNone The name was read successfully. @p aOffset and @p aNameBuffer are updated. 2288 * @retval kErrorParse The SIG record in @p aMessage could not be parsed (invalid format). 2289 * @retval kErrorNoBufs Name could not fit in @p aNameBufferSize chars. 2290 */ ReadSignerName(const Message & aMessage,uint16_t & aOffset,char * aNameBuffer,uint16_t aNameBufferSize) const2291 Error ReadSignerName(const Message &aMessage, uint16_t &aOffset, char *aNameBuffer, uint16_t aNameBufferSize) const 2292 { 2293 return ResourceRecord::ReadName(aMessage, aOffset, /* aStartOffset */ aOffset - sizeof(SigRecord), aNameBuffer, 2294 aNameBufferSize, 2295 /* aSkipRecord */ false); 2296 } 2297 2298 private: 2299 uint16_t mTypeCovered; // type of the other RRs covered by this SIG. set to zero for SIG(0). 2300 uint8_t mAlgorithm; // Algorithm number (see `KeyRecord` enumeration). 2301 uint8_t mLabels; // Number of labels (not counting null label) in the original name of the owner of RR. 2302 uint32_t mOriginalTtl; // Original time-to-live (should set to zero for SIG(0)). 2303 uint32_t mExpiration; // Signature expiration time (seconds since Jan 1, 1970). 2304 uint32_t mInception; // Signature inception time (seconds since Jan 1, 1970). 2305 uint16_t mKeyTag; // Key tag. 2306 // Followed by signer name fields and signature fields 2307 } OT_TOOL_PACKED_END; 2308 2309 /** 2310 * Implements DNS OPT Pseudo Resource Record header for EDNS(0) (RFC 6891 - Section 6.1). 2311 */ 2312 OT_TOOL_PACKED_BEGIN 2313 class OptRecord : public ResourceRecord 2314 { 2315 public: 2316 static constexpr uint16_t kType = kTypeOpt; ///< The OPT record type. 2317 2318 /** 2319 * Initializes the OPT Resource Record by setting its type and clearing extended Response Code, version 2320 * and all flags. 2321 * 2322 * Other record fields (UDP payload size, length) remain unchanged/uninitialized. 2323 */ Init(void)2324 void Init(void) 2325 { 2326 SetType(kTypeOpt); 2327 SetTtl(0); 2328 } 2329 2330 /** 2331 * Gets the requester's UDP payload size (the number of bytes of the largest UDP payload that can be 2332 * delivered in the requester's network). 2333 * 2334 * The field is encoded in the CLASS field. 2335 * 2336 * @returns The UDP payload size. 2337 */ GetUdpPayloadSize(void) const2338 uint16_t GetUdpPayloadSize(void) const { return GetClass(); } 2339 2340 /** 2341 * Gets the requester's UDP payload size (the number of bytes of the largest UDP payload that can be 2342 * delivered in the requester's network). 2343 * 2344 * @param[in] aPayloadSize The UDP payload size. 2345 */ SetUdpPayloadSize(uint16_t aPayloadSize)2346 void SetUdpPayloadSize(uint16_t aPayloadSize) { SetClass(aPayloadSize); } 2347 2348 /** 2349 * Gets the upper 8-bit of the extended 12-bit Response Code. 2350 * 2351 * Value of 0 indicates that an unextended Response code is in use. 2352 * 2353 * @return The upper 8-bit of the extended 12-bit Response Code. 2354 */ GetExtendedResponseCode(void) const2355 uint8_t GetExtendedResponseCode(void) const { return GetTtlByteAt(kExtRCodeByteIndex); } 2356 2357 /** 2358 * Sets the upper 8-bit of the extended 12-bit Response Code. 2359 * 2360 * Value of 0 indicates that an unextended Response code is in use. 2361 * 2362 * @param[in] aExtendedResponse The upper 8-bit of the extended 12-bit Response Code. 2363 */ SetExtendedResponseCode(uint8_t aExtendedResponse)2364 void SetExtendedResponseCode(uint8_t aExtendedResponse) { GetTtlByteAt(kExtRCodeByteIndex) = aExtendedResponse; } 2365 2366 /** 2367 * Gets the Version field. 2368 * 2369 * @returns The version. 2370 */ GetVersion(void) const2371 uint8_t GetVersion(void) const { return GetTtlByteAt(kVersionByteIndex); } 2372 2373 /** 2374 * Set the Version field. 2375 * 2376 * @param[in] aVersion The version. 2377 */ SetVersion(uint8_t aVersion)2378 void SetVersion(uint8_t aVersion) { GetTtlByteAt(kVersionByteIndex) = aVersion; } 2379 2380 /** 2381 * Indicates whether the DNSSEC OK flag is set or not. 2382 * 2383 * @returns True if DNSSEC OK flag is set in the header, false otherwise. 2384 */ IsDnsSecurityFlagSet(void) const2385 bool IsDnsSecurityFlagSet(void) const { return (GetTtlByteAt(kFlagByteIndex) & kDnsSecFlag) != 0; } 2386 2387 /** 2388 * Clears the DNSSEC OK bit flag. 2389 */ ClearDnsSecurityFlag(void)2390 void ClearDnsSecurityFlag(void) { GetTtlByteAt(kFlagByteIndex) &= ~kDnsSecFlag; } 2391 2392 /** 2393 * Sets the DNSSEC OK bit flag. 2394 */ SetDnsSecurityFlag(void)2395 void SetDnsSecurityFlag(void) { GetTtlByteAt(kFlagByteIndex) |= kDnsSecFlag; } 2396 2397 private: 2398 // The OPT RR re-purposes the existing CLASS and TTL fields in the 2399 // RR. The CLASS field (`uint16_t`) is used for requester UDP 2400 // payload size. The TTL field is used for extended Response Code, 2401 // version and flags as follows: 2402 // 2403 // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 2404 // +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ 2405 // | EXTENDED-RCODE | VERSION | 2406 // +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ 2407 // | DO| Z | Z | 2408 // +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ 2409 // 2410 // The variable data part of OPT RR can contain zero of more `Option`. 2411 2412 static constexpr uint8_t kExtRCodeByteIndex = 0; // Byte index of Extended RCODE within the TTL field. 2413 static constexpr uint8_t kVersionByteIndex = 1; // Byte index of Version within the TTL field. 2414 static constexpr uint8_t kFlagByteIndex = 2; // Byte index of flag byte within the TTL field. 2415 static constexpr uint8_t kDnsSecFlag = 1 << 7; // DNSSec OK bit flag. 2416 GetTtlByteAt(uint8_t aIndex) const2417 uint8_t GetTtlByteAt(uint8_t aIndex) const { return reinterpret_cast<const uint8_t *>(&mTtl)[aIndex]; } GetTtlByteAt(uint8_t aIndex)2418 uint8_t &GetTtlByteAt(uint8_t aIndex) { return reinterpret_cast<uint8_t *>(&mTtl)[aIndex]; } 2419 2420 } OT_TOOL_PACKED_END; 2421 2422 /** 2423 * Implements the body of an Option in OPT Pseudo Resource Record (RFC 6981 - Section 6.1). 2424 */ 2425 OT_TOOL_PACKED_BEGIN 2426 class Option 2427 { 2428 public: 2429 static constexpr uint16_t kUpdateLease = 2; ///< Update lease option code. 2430 2431 /** 2432 * Returns the option code value. 2433 * 2434 * @returns The option code value. 2435 */ GetOptionCode(void) const2436 uint16_t GetOptionCode(void) const { return BigEndian::HostSwap16(mOptionCode); } 2437 2438 /** 2439 * Sets the option code value. 2440 * 2441 * @param[in] aOptionCode The option code value. 2442 */ SetOptionCode(uint16_t aOptionCode)2443 void SetOptionCode(uint16_t aOptionCode) { mOptionCode = BigEndian::HostSwap16(aOptionCode); } 2444 2445 /** 2446 * Returns the option length value. 2447 * 2448 * @returns The option length (size of option data in bytes). 2449 */ GetOptionLength(void) const2450 uint16_t GetOptionLength(void) const { return BigEndian::HostSwap16(mOptionLength); } 2451 2452 /** 2453 * Sets the option length value. 2454 * 2455 * @param[in] aOptionLength The option length (size of option data in bytes). 2456 */ SetOptionLength(uint16_t aOptionLength)2457 void SetOptionLength(uint16_t aOptionLength) { mOptionLength = BigEndian::HostSwap16(aOptionLength); } 2458 2459 /** 2460 * Returns the size of (number of bytes) in the Option and its data. 2461 * 2462 * @returns Size (number of bytes) of the Option its data section. 2463 */ GetSize(void) const2464 uint32_t GetSize(void) const { return sizeof(Option) + GetOptionLength(); } 2465 2466 private: 2467 uint16_t mOptionCode; 2468 uint16_t mOptionLength; 2469 // Followed by Option data (varies per option code). 2470 2471 } OT_TOOL_PACKED_END; 2472 2473 /** 2474 * Implements an Update Lease Option body. 2475 * 2476 * This implementation is intended for use in Dynamic DNS Update Lease Requests and Responses as specified in 2477 * https://tools.ietf.org/html/draft-sekar-dns-ul-02. 2478 */ 2479 OT_TOOL_PACKED_BEGIN 2480 class LeaseOption : public Option 2481 { 2482 public: 2483 /** 2484 * Initializes the Update Lease Option using the short variant format which contains lease interval 2485 * only. 2486 * 2487 * @param[in] aLeaseInterval The lease interval in seconds. 2488 */ 2489 void InitAsShortVariant(uint32_t aLeaseInterval); 2490 2491 /** 2492 * Initializes the Update Lease Option using the long variant format which contains both lease and 2493 * key lease intervals. 2494 * 2495 * @param[in] aLeaseInterval The lease interval in seconds. 2496 * @param[in] aKeyLeaseInterval The key lease interval in seconds. 2497 */ 2498 void InitAsLongVariant(uint32_t aLeaseInterval, uint32_t aKeyLeaseInterval); 2499 2500 /** 2501 * Indicates whether or not the Update Lease Option follows the short variant format which contains 2502 * only the lease interval. 2503 * 2504 * @retval TRUE The Update Lease Option follows the short variant format. 2505 * @retval FALSE The Update Lease Option follows the long variant format. 2506 */ IsShortVariant(void) const2507 bool IsShortVariant(void) const { return (GetOptionLength() == kShortLength); } 2508 2509 /** 2510 * Tells whether this is a valid Lease Option. 2511 * 2512 * Validates that option follows either short or long variant format. 2513 * 2514 * @returns TRUE if this is a valid Lease Option, FALSE if not a valid Lease Option. 2515 */ 2516 bool IsValid(void) const; 2517 2518 /** 2519 * Returns the Update Lease OPT record's lease interval value. 2520 * 2521 * @returns The lease interval value (in seconds). 2522 */ GetLeaseInterval(void) const2523 uint32_t GetLeaseInterval(void) const { return BigEndian::HostSwap32(mLeaseInterval); } 2524 2525 /** 2526 * Returns the Update Lease OPT record's key lease interval value. 2527 * 2528 * If the Update Lease Option follows the short variant format the lease interval is returned as key lease interval. 2529 * 2530 * @returns The key lease interval value (in seconds). 2531 */ GetKeyLeaseInterval(void) const2532 uint32_t GetKeyLeaseInterval(void) const 2533 { 2534 return IsShortVariant() ? GetLeaseInterval() : BigEndian::HostSwap32(mKeyLeaseInterval); 2535 } 2536 2537 /** 2538 * Searches among the Options is a given message and reads and validates the Update Lease Option if 2539 * found. 2540 * 2541 * Reads the Update Lease Option whether it follows the short or long variant formats. 2542 * 2543 * @param[in] aMessage The message to read the Option from. 2544 * @param[in] aOffset Offset in @p aMessage to the start of Options (start of OPT Record data). 2545 * @param[in] aLength Length of Option data in OPT record. 2546 * 2547 * @retval kErrorNone Successfully read and validated the Update Lease Option from @p aMessage. 2548 * @retval kErrorNotFound Did not find any Update Lease Option. 2549 * @retval kErrorParse Failed to parse the Options. 2550 */ 2551 Error ReadFrom(const Message &aMessage, uint16_t aOffset, uint16_t aLength); 2552 2553 private: 2554 static constexpr uint16_t kShortLength = sizeof(uint32_t); // lease only. 2555 static constexpr uint16_t kLongLength = sizeof(uint32_t) + sizeof(uint32_t); // lease and key lease values 2556 SetLeaseInterval(uint32_t aLeaseInterval)2557 void SetLeaseInterval(uint32_t aLeaseInterval) { mLeaseInterval = BigEndian::HostSwap32(aLeaseInterval); } SetKeyLeaseInterval(uint32_t aKeyLeaseInterval)2558 void SetKeyLeaseInterval(uint32_t aKeyLeaseInterval) 2559 { 2560 mKeyLeaseInterval = BigEndian::HostSwap32(aKeyLeaseInterval); 2561 } 2562 2563 uint32_t mLeaseInterval; 2564 uint32_t mKeyLeaseInterval; 2565 } OT_TOOL_PACKED_END; 2566 2567 /** 2568 * Implements body format of NSEC record (RFC 3845) for use with mDNS. 2569 */ 2570 OT_TOOL_PACKED_BEGIN 2571 class NsecRecord : public ResourceRecord 2572 { 2573 public: 2574 static constexpr uint16_t kType = kTypeNsec; ///< The NSEC record type. 2575 2576 /** 2577 * Represents NSEC Type Bit Map field (RFC 3845 - section 2.1.2) 2578 */ 2579 OT_TOOL_PACKED_BEGIN 2580 class TypeBitMap : public Clearable<TypeBitMap> 2581 { 2582 public: 2583 static constexpr uint8_t kMinSize = 2; ///< Minimum size of a valid `TypeBitMap` (with zero length). 2584 2585 static constexpr uint8_t kMaxLength = 32; ///< Maximum BitmapLength value. 2586 2587 /** 2588 * Gets the Window Block Number 2589 * 2590 * @returns The Window Block Number. 2591 */ GetBlockNumber(void) const2592 uint8_t GetBlockNumber(void) const { return mBlockNumber; } 2593 2594 /** 2595 * Sets the Window Block Number 2596 * 2597 * @param[in] aBlockNumber The Window Block Number. 2598 */ SetBlockNumber(uint8_t aBlockNumber)2599 void SetBlockNumber(uint8_t aBlockNumber) { mBlockNumber = aBlockNumber; } 2600 2601 /** 2602 * Gets the Bitmap length 2603 * 2604 * @returns The Bitmap length 2605 */ GetBitmapLength(void)2606 uint8_t GetBitmapLength(void) { return mBitmapLength; } 2607 2608 /** 2609 * Gets the total size (number of bytes) of the `TypeBitMap` field. 2610 * 2611 * @returns The size of the `TypeBitMap` 2612 */ GetSize(void) const2613 uint16_t GetSize(void) const { return (sizeof(mBlockNumber) + sizeof(mBitmapLength) + mBitmapLength); } 2614 2615 /** 2616 * Adds a resource record type to the Bitmap. 2617 * 2618 * As the types are added to the Bitmap the Bitmap length gets updated accordingly. 2619 * 2620 * The type space is split into 256 window blocks, each representing the low-order 8 bits of the 16-bit type 2621 * value. If @p aType does not match the currently set Window Block Number, no action is performed. 2622 * 2623 * @param[in] aType The resource record type to add. 2624 */ 2625 void AddType(uint16_t aType); 2626 2627 /** 2628 * Indicates whether a given resource record type is present in the Bitmap. 2629 * 2630 * If @p aType does not match the currently set Window Block Number, this method returns `false`.. 2631 * 2632 * @param[in] aType The resource record type to check. 2633 * 2634 * @retval TRUE The @p aType is present in the Bitmap. 2635 * @retval FALSE The @p aType is not present in the Bitmap. 2636 */ 2637 bool ContainsType(uint16_t aType) const; 2638 2639 private: 2640 uint8_t mBlockNumber; 2641 uint8_t mBitmapLength; 2642 uint8_t mBitmaps[kMaxLength]; 2643 } OT_TOOL_PACKED_END; 2644 2645 /** 2646 * Initializes the NSEC Resource Record by setting its type and class. 2647 * 2648 * Other record fields (TTL, length remain unchanged/uninitialized. 2649 * 2650 * @param[in] aClass The class of the resource record (default is `kClassInternet`). 2651 */ Init(uint16_t aClass=kClassInternet)2652 void Init(uint16_t aClass = kClassInternet) { ResourceRecord::Init(kTypeNsec, aClass); } 2653 2654 } OT_TOOL_PACKED_END; 2655 2656 /** 2657 * Implements Question format. 2658 */ 2659 OT_TOOL_PACKED_BEGIN 2660 class Question 2661 { 2662 public: 2663 /** 2664 * Default constructor for Question 2665 */ 2666 Question(void) = default; 2667 2668 /** 2669 * Constructor for Question. 2670 */ Question(uint16_t aType,uint16_t aClass=ResourceRecord::kClassInternet)2671 explicit Question(uint16_t aType, uint16_t aClass = ResourceRecord::kClassInternet) 2672 { 2673 SetType(aType); 2674 SetClass(aClass); 2675 } 2676 2677 /** 2678 * Returns the type of the question. 2679 * 2680 * @returns The type of the question. 2681 */ GetType(void) const2682 uint16_t GetType(void) const { return BigEndian::HostSwap16(mType); } 2683 2684 /** 2685 * Sets the type of the question. 2686 * 2687 * @param[in] aType The type of the question. 2688 */ SetType(uint16_t aType)2689 void SetType(uint16_t aType) { mType = BigEndian::HostSwap16(aType); } 2690 2691 /** 2692 * Returns the class of the question. 2693 * 2694 * @returns The class of the question. 2695 */ GetClass(void) const2696 uint16_t GetClass(void) const { return BigEndian::HostSwap16(mClass); } 2697 2698 /** 2699 * Sets the class of the question. 2700 * 2701 * @param[in] aClass The class of the question. 2702 */ SetClass(uint16_t aClass)2703 void SetClass(uint16_t aClass) { mClass = BigEndian::HostSwap16(aClass); } 2704 2705 private: 2706 uint16_t mType; // The type of the data in question section. 2707 uint16_t mClass; // The class of the data in question section. 2708 } OT_TOOL_PACKED_END; 2709 2710 /** 2711 * Implements Zone section body for DNS Update (RFC 2136 - section 2.3). 2712 */ 2713 OT_TOOL_PACKED_BEGIN 2714 class Zone : public Question 2715 { 2716 public: 2717 /** 2718 * Constructor for Zone. 2719 * 2720 * @param[in] aClass The class of the zone (default is `kClassInternet`). 2721 */ Zone(uint16_t aClass=ResourceRecord::kClassInternet)2722 explicit Zone(uint16_t aClass = ResourceRecord::kClassInternet) 2723 : Question(ResourceRecord::kTypeSoa, aClass) 2724 { 2725 } 2726 } OT_TOOL_PACKED_END; 2727 2728 /** 2729 * @} 2730 */ 2731 2732 } // namespace Dns 2733 2734 DefineCoreType(otDnsTxtEntry, Dns::TxtEntry); 2735 DefineCoreType(otDnsTxtEntryIterator, Dns::TxtEntry::Iterator); 2736 2737 } // namespace ot 2738 2739 #endif // DNS_HEADER_HPP_ 2740