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 * Encodes and appends the `TxtEntry` to an Appender object. 1216 * 1217 * @param[in] aAppender The appender to append to. 1218 * 1219 * @retval kErrorNone Entry was appended successfully to @p aAppender. 1220 * @retval kErrorInvalidArgs The `TxTEntry` info is not valid. 1221 * @retval kErrorNoBufs Insufficient available space in @p aAppender. 1222 */ 1223 Error AppendTo(Appender &aAppender) const; 1224 1225 /** 1226 * Appends an array of `TxtEntry` items to a message. 1227 * 1228 * @param[in] aEntries A pointer to array of `TxtEntry` items. 1229 * @param[in] aNumEntries The number of entries in @p aEntries array. 1230 * @param[in] aMessage The message to append to. 1231 * 1232 * @retval kErrorNone Entries appended successfully to @p aMessage. 1233 * @retval kErrorInvalidArgs The `TxTEntry` info is not valid. 1234 * @retval kErrorNoBufs Insufficient available buffers to grow the message. 1235 */ 1236 static Error AppendEntries(const TxtEntry *aEntries, uint16_t aNumEntries, Message &aMessage); 1237 1238 /** 1239 * Appends an array of `TxtEntry` items to a `MutableData` buffer. 1240 * 1241 * @param[in] aEntries A pointer to array of `TxtEntry` items. 1242 * @param[in] aNumEntries The number of entries in @p aEntries array. 1243 * @param[in] aData The `MutableData` to append in. 1244 * 1245 * @retval kErrorNone Entries appended successfully . 1246 * @retval kErrorInvalidArgs The `TxTEntry` info is not valid. 1247 * @retval kErrorNoBufs Insufficient available buffers. 1248 */ 1249 static Error AppendEntries(const TxtEntry *aEntries, uint16_t aNumEntries, MutableData<kWithUint16Length> &aData); 1250 1251 private: 1252 static Error AppendEntries(const TxtEntry *aEntries, uint16_t aNumEntries, Appender &aAppender); 1253 1254 static constexpr uint8_t kMaxKeyValueEncodedSize = 255; 1255 static constexpr char kKeyValueSeparator = '='; 1256 }; 1257 1258 /** 1259 * Implements Resource Record (RR) body format. 1260 */ 1261 OT_TOOL_PACKED_BEGIN 1262 class ResourceRecord 1263 { 1264 friend class OptRecord; 1265 1266 public: 1267 // Resource Record Types. 1268 static constexpr uint16_t kTypeZero = 0; ///< Zero as special indicator for the SIG RR (SIG(0) from RFC 2931). 1269 static constexpr uint16_t kTypeA = 1; ///< Address record (IPv4). 1270 static constexpr uint16_t kTypeSoa = 6; ///< Start of (zone of) authority. 1271 static constexpr uint16_t kTypeCname = 5; ///< CNAME record. 1272 static constexpr uint16_t kTypePtr = 12; ///< PTR record. 1273 static constexpr uint16_t kTypeTxt = 16; ///< TXT record. 1274 static constexpr uint16_t kTypeSig = 24; ///< SIG record. 1275 static constexpr uint16_t kTypeKey = 25; ///< KEY record. 1276 static constexpr uint16_t kTypeAaaa = 28; ///< IPv6 address record. 1277 static constexpr uint16_t kTypeSrv = 33; ///< SRV locator record. 1278 static constexpr uint16_t kTypeOpt = 41; ///< Option record. 1279 static constexpr uint16_t kTypeNsec = 47; ///< NSEC record. 1280 static constexpr uint16_t kTypeAny = 255; ///< ANY record. 1281 1282 // Resource Record Class Codes. 1283 static constexpr uint16_t kClassInternet = 1; ///< Class code Internet (IN). 1284 static constexpr uint16_t kClassNone = 254; ///< Class code None (NONE) - RFC 2136. 1285 static constexpr uint16_t kClassAny = 255; ///< Class code Any (ANY). 1286 1287 /** 1288 * Initializes the resource record by setting its type and class. 1289 * 1290 * Only sets the type and class fields. Other fields (TTL and length) remain unchanged/uninitialized. 1291 * 1292 * @param[in] aType The type of the resource record. 1293 * @param[in] aClass The class of the resource record (default is `kClassInternet`). 1294 */ Init(uint16_t aType,uint16_t aClass=kClassInternet)1295 void Init(uint16_t aType, uint16_t aClass = kClassInternet) 1296 { 1297 SetType(aType); 1298 SetClass(aClass); 1299 } 1300 1301 /** 1302 * Indicates whether the resources records matches a given type and class code. 1303 * 1304 * @param[in] aType The resource record type to compare with. 1305 * @param[in] aClass The resource record class code to compare with (default is `kClassInternet`). 1306 * 1307 * @returns TRUE if the resources records matches @p aType and @p aClass, FALSE otherwise. 1308 */ Matches(uint16_t aType,uint16_t aClass=kClassInternet) const1309 bool Matches(uint16_t aType, uint16_t aClass = kClassInternet) const 1310 { 1311 return (mType == BigEndian::HostSwap16(aType)) && (mClass == BigEndian::HostSwap16(aClass)); 1312 } 1313 1314 /** 1315 * Returns the type of the resource record. 1316 * 1317 * @returns The type of the resource record. 1318 */ GetType(void) const1319 uint16_t GetType(void) const { return BigEndian::HostSwap16(mType); } 1320 1321 /** 1322 * Sets the type of the resource record. 1323 * 1324 * @param[in] aType The type of the resource record. 1325 */ SetType(uint16_t aType)1326 void SetType(uint16_t aType) { mType = BigEndian::HostSwap16(aType); } 1327 1328 /** 1329 * Returns the class of the resource record. 1330 * 1331 * @returns The class of the resource record. 1332 */ GetClass(void) const1333 uint16_t GetClass(void) const { return BigEndian::HostSwap16(mClass); } 1334 1335 /** 1336 * Sets the class of the resource record. 1337 * 1338 * @param[in] aClass The class of the resource record. 1339 */ SetClass(uint16_t aClass)1340 void SetClass(uint16_t aClass) { mClass = BigEndian::HostSwap16(aClass); } 1341 1342 /** 1343 * Returns the time to live field of the resource record. 1344 * 1345 * @returns The time to live field of the resource record. 1346 */ GetTtl(void) const1347 uint32_t GetTtl(void) const { return BigEndian::HostSwap32(mTtl); } 1348 1349 /** 1350 * Sets the time to live field of the resource record. 1351 * 1352 * @param[in] aTtl The time to live field of the resource record. 1353 */ SetTtl(uint32_t aTtl)1354 void SetTtl(uint32_t aTtl) { mTtl = BigEndian::HostSwap32(aTtl); } 1355 1356 /** 1357 * Returns the length of the resource record data. 1358 * 1359 * @returns The length of the resource record data. 1360 */ GetLength(void) const1361 uint16_t GetLength(void) const { return BigEndian::HostSwap16(mLength); } 1362 1363 /** 1364 * Sets the length of the resource record data. 1365 * 1366 * @param[in] aLength The length of the resource record data. 1367 */ SetLength(uint16_t aLength)1368 void SetLength(uint16_t aLength) { mLength = BigEndian::HostSwap16(aLength); } 1369 1370 /** 1371 * Returns the size of (number of bytes) in resource record and its data RDATA section (excluding the 1372 * name field). 1373 * 1374 * @returns Size (number of bytes) of resource record and its data section (excluding the name field) 1375 */ GetSize(void) const1376 uint32_t GetSize(void) const { return sizeof(ResourceRecord) + GetLength(); } 1377 1378 /** 1379 * Parses and skips over a given number of resource records in a message from a given offset. 1380 * 1381 * @param[in] aMessage The message from which to parse/read the resource records. `aMessage.GetOffset()` 1382 * MUST point to the start of DNS header. 1383 * @param[in,out] aOffset On input the offset in @p aMessage pointing to the start of the first record. 1384 * On exit (when parsed successfully), @p aOffset is updated to point to the byte after 1385 * the last parsed record. 1386 * @param[in] aNumRecords Number of resource records to parse. 1387 * 1388 * @retval kErrorNone Parsed records successfully. @p aOffset is updated. 1389 * @retval kErrorParse Could not parse the records from @p aMessage (e.g., ran out of bytes in @p aMessage). 1390 */ 1391 static Error ParseRecords(const Message &aMessage, uint16_t &aOffset, uint16_t aNumRecords); 1392 1393 /** 1394 * Searches in a given message to find the first resource record matching a given record name. 1395 * 1396 * @param[in] aMessage The message in which to search for a matching resource record. 1397 * `aMessage.GetOffset()` MUST point to the start of DNS header. 1398 * @param[in,out] aOffset On input, the offset in @p aMessage pointing to the start of the first record. 1399 * On exit, if a matching record is found, @p aOffset is updated to point to the byte 1400 * after the record name. 1401 * If a matching record could not be found, @p aOffset is updated to point to the byte 1402 * after the last record that was checked. 1403 * @param[in,out] aNumRecords On input, the maximum number of records to check (starting from @p aOffset). 1404 * On exit and if a matching record is found, @p aNumRecords is updated to give the 1405 * number of remaining records after @p aOffset (excluding the matching record). 1406 * @param[in] aName The record name to match against. 1407 * 1408 * @retval kErrorNone A matching record was found. @p aOffset, @p aNumRecords are updated. 1409 * @retval kErrorNotFound A matching record could not be found. @p aOffset and @p aNumRecords are updated. 1410 * @retval kErrorParse Could not parse records from @p aMessage (e.g., ran out of bytes in @p aMessage). 1411 */ 1412 static Error FindRecord(const Message &aMessage, uint16_t &aOffset, uint16_t &aNumRecords, const Name &aName); 1413 1414 /** 1415 * This template static method searches in a message to find the i-th occurrence of resource records of specific 1416 * type with a given record name and if found, reads the record from the message. 1417 * 1418 * Searches in @p aMessage starting from @p aOffset up to maximum of @p aNumRecords, for the 1419 * `(aIndex+1)`th occurrence of a resource record of `RecordType` with record name @p aName. 1420 * 1421 * On success (i.e., when a matching record is found and read from the message), @p aOffset is updated to point 1422 * to after the last byte read from the message and copied into @p aRecord. This allows the caller to read any 1423 * remaining fields in the record data. 1424 * 1425 * @tparam RecordType The resource record type (i.e., a sub-class of `ResourceRecord`). 1426 * 1427 * @param[in] aMessage The message to search within for matching resource records. 1428 * `aMessage.GetOffset()` MUST point to the start of DNS header. 1429 * @param[in,out] aOffset On input, the offset in @p aMessage pointing to the start of the first record. 1430 * On exit and only if a matching record is found, @p aOffset is updated to point to 1431 * the last read byte in the record (allowing caller to read any remaining fields in 1432 * the record data from the message). 1433 * @param[in] aNumRecords The maximum number of records to check (starting from @p aOffset). 1434 * @param[in] aIndex The matching record index to find. @p aIndex value of zero returns the first 1435 * matching record. 1436 * @param[in] aName The record name to match against. 1437 * @param[in] aRecord A reference to a record object to read a matching record into. 1438 * If a matching record is found, `sizeof(RecordType)` bytes from @p aMessage are 1439 * read and copied into @p aRecord. 1440 * 1441 * @retval kErrorNone A matching record was found. @p aOffset is updated. 1442 * @retval kErrorNotFound A matching record could not be found. 1443 * @retval kErrorParse Could not parse records from @p aMessage (e.g., ran out of bytes in @p aMessage). 1444 */ 1445 template <class RecordType> FindRecord(const Message & aMessage,uint16_t & aOffset,uint16_t aNumRecords,uint16_t aIndex,const Name & aName,RecordType & aRecord)1446 static Error FindRecord(const Message &aMessage, 1447 uint16_t &aOffset, 1448 uint16_t aNumRecords, 1449 uint16_t aIndex, 1450 const Name &aName, 1451 RecordType &aRecord) 1452 { 1453 return FindRecord(aMessage, aOffset, aNumRecords, aIndex, aName, RecordType::kType, aRecord, 1454 sizeof(RecordType)); 1455 } 1456 1457 /** 1458 * This template static method tries to read a resource record of a given type from a message. If the record type 1459 * does not matches the type, it skips over the record. 1460 * 1461 * Requires the record name to be already parsed/read from the message. On input, @p aOffset should 1462 * point to the start of the `ResourceRecord` fields (type, class, TTL, data length) in @p aMessage. 1463 * 1464 * Verifies that the record is well-formed in the message. It then reads the record type and compares 1465 * it with `RecordType::kType` and ensures that the record size is at least `sizeof(RecordType)`. If it all matches, 1466 * the record is read into @p aRecord. 1467 * 1468 * On success (i.e., when a matching record is read from the message), the @p aOffset is updated to point to after 1469 * the last byte read from the message and copied into @p aRecord and not necessarily the end of the record. 1470 * Depending on the `RecordType` format, there may still be more data bytes left in the record to be read. For 1471 * example, when reading a SRV record using `SrvRecord` type, @p aOffset would point to after the last field in 1472 * `SrvRecord` which is the start of "target host domain name" field. 1473 * 1474 * @tparam RecordType The resource record type (i.e., a sub-class of `ResourceRecord`). 1475 * 1476 * @param[in] aMessage The message from which to read the record. 1477 * @param[in,out] aOffset On input, the offset in @p aMessage pointing to the byte after the record name. 1478 * On exit, if a matching record is read, @p aOffset is updated to point to the last 1479 * read byte in the record. 1480 * If a matching record could not be read, @p aOffset is updated to point to the byte 1481 * after the entire record (skipping over the record). 1482 * @param[out] aRecord A reference to a record to read a matching record into. 1483 * If a matching record is found, `sizeof(RecordType)` bytes from @p aMessage are 1484 * read and copied into @p aRecord. 1485 * 1486 * @retval kErrorNone A matching record was read successfully. @p aOffset, and @p aRecord are updated. 1487 * @retval kErrorNotFound A matching record could not be found. @p aOffset is updated. 1488 * @retval kErrorParse Could not parse records from @p aMessage (e.g., ran out of bytes in @p aMessage). 1489 */ ReadRecord(const Message & aMessage,uint16_t & aOffset,RecordType & aRecord)1490 template <class RecordType> static Error ReadRecord(const Message &aMessage, uint16_t &aOffset, RecordType &aRecord) 1491 { 1492 return ReadRecord(aMessage, aOffset, RecordType::kType, aRecord, sizeof(RecordType)); 1493 } 1494 1495 protected: 1496 Error ReadName(const Message &aMessage, 1497 uint16_t &aOffset, 1498 uint16_t aStartOffset, 1499 char *aNameBuffer, 1500 uint16_t aNameBufferSize, 1501 bool aSkipRecord) const; 1502 Error SkipRecord(const Message &aMessage, uint16_t &aOffset) const; 1503 1504 private: 1505 static constexpr uint16_t kType = kTypeAny; // This is intended for used by `ReadRecord<RecordType>()` only. 1506 1507 static Error FindRecord(const Message &aMessage, 1508 uint16_t &aOffset, 1509 uint16_t aNumRecords, 1510 uint16_t aIndex, 1511 const Name &aName, 1512 uint16_t aType, 1513 ResourceRecord &aRecord, 1514 uint16_t aMinRecordSize); 1515 1516 static Error ReadRecord(const Message &aMessage, 1517 uint16_t &aOffset, 1518 uint16_t aType, 1519 ResourceRecord &aRecord, 1520 uint16_t aMinRecordSize); 1521 1522 Error CheckRecord(const Message &aMessage, uint16_t aOffset) const; 1523 Error ReadFrom(const Message &aMessage, uint16_t aOffset); 1524 1525 uint16_t mType; // The type of the data in RDATA section. 1526 uint16_t mClass; // The class of the data in RDATA section. 1527 uint32_t mTtl; // Specifies the maximum time that the resource record may be cached. 1528 uint16_t mLength; // The length of RDATA section in bytes. 1529 1530 } OT_TOOL_PACKED_END; 1531 1532 /** 1533 * Implements Resource Record body format of A type. 1534 */ 1535 OT_TOOL_PACKED_BEGIN 1536 class ARecord : public ResourceRecord 1537 { 1538 public: 1539 static constexpr uint16_t kType = kTypeA; ///< The A record type. 1540 1541 /** 1542 * Initializes the A Resource Record by setting its type, class, and length. 1543 * 1544 * Other record fields (TTL, address) remain unchanged/uninitialized. 1545 */ Init(void)1546 void Init(void) 1547 { 1548 ResourceRecord::Init(kTypeA); 1549 SetLength(sizeof(Ip4::Address)); 1550 } 1551 1552 /** 1553 * Sets the IPv4 address of the resource record. 1554 * 1555 * @param[in] aAddress The IPv4 address of the resource record. 1556 */ SetAddress(const Ip4::Address & aAddress)1557 void SetAddress(const Ip4::Address &aAddress) { mAddress = aAddress; } 1558 1559 /** 1560 * Returns the reference to IPv4 address of the resource record. 1561 * 1562 * @returns The reference to IPv4 address of the resource record. 1563 */ GetAddress(void) const1564 const Ip4::Address &GetAddress(void) const { return mAddress; } 1565 1566 private: 1567 Ip4::Address mAddress; // IPv4 Address of A Resource Record. 1568 } OT_TOOL_PACKED_END; 1569 1570 /** 1571 * Implements Resource Record body format of CNAME type. 1572 */ 1573 OT_TOOL_PACKED_BEGIN 1574 class CnameRecord : public ResourceRecord 1575 { 1576 public: 1577 static constexpr uint16_t kType = kTypeCname; ///< The CNAME record type. 1578 1579 /** 1580 * Initializes the CNAME Resource Record by setting its type and class. 1581 * 1582 * Other record fields (TTL, length) remain unchanged/uninitialized. 1583 * 1584 * @param[in] aClass The class of the resource record (default is `kClassInternet`). 1585 */ Init(uint16_t aClass=kClassInternet)1586 void Init(uint16_t aClass = kClassInternet) { ResourceRecord::Init(kTypeCname, aClass); } 1587 1588 /** 1589 * Parses and reads the CNAME alias name from a message. 1590 * 1591 * Also verifies that the CNAME record is well-formed (e.g., the record data length `GetLength()` 1592 * matches the CNAME encoded name). 1593 * 1594 * @param[in] aMessage The message to read from. `aMessage.GetOffset()` MUST point to the start of 1595 * DNS header. 1596 * @param[in,out] aOffset On input, the offset in @p aMessage to start of CNAME name field. 1597 * On exit when successfully read, @p aOffset is updated to point to the byte 1598 * after the entire PTR record (skipping over the record). 1599 * @param[out] aNameBuffer A pointer to a char array to output the read name as a null-terminated C string 1600 * (MUST NOT be `nullptr`). 1601 * @param[in] aNameBufferSize The size of @p aNameBuffer. 1602 * 1603 * @retval kErrorNone The CNAME name was read successfully. @p aOffset and @p aNameBuffer are updated. 1604 * @retval kErrorParse The CNAME record in @p aMessage could not be parsed (invalid format). 1605 * @retval kErrorNoBufs Name could not fit in @p aNameBufferSize chars. 1606 */ ReadCanonicalName(const Message & aMessage,uint16_t & aOffset,char * aNameBuffer,uint16_t aNameBufferSize) const1607 Error ReadCanonicalName(const Message &aMessage, 1608 uint16_t &aOffset, 1609 char *aNameBuffer, 1610 uint16_t aNameBufferSize) const 1611 { 1612 return ResourceRecord::ReadName(aMessage, aOffset, /* aStartOffset */ aOffset - sizeof(CnameRecord), 1613 aNameBuffer, aNameBufferSize, /* aSkipRecord */ true); 1614 } 1615 1616 } OT_TOOL_PACKED_END; 1617 1618 /** 1619 * Implements Resource Record body format of PTR type. 1620 */ 1621 OT_TOOL_PACKED_BEGIN 1622 class PtrRecord : public ResourceRecord 1623 { 1624 public: 1625 static constexpr uint16_t kType = kTypePtr; ///< The PTR record type. 1626 1627 /** 1628 * Initializes the PTR Resource Record by setting its type and class. 1629 * 1630 * Other record fields (TTL, length) remain unchanged/uninitialized. 1631 * 1632 * @param[in] aClass The class of the resource record (default is `kClassInternet`). 1633 */ Init(uint16_t aClass=kClassInternet)1634 void Init(uint16_t aClass = kClassInternet) { ResourceRecord::Init(kTypePtr, aClass); } 1635 1636 /** 1637 * Parses and reads the PTR name from a message. 1638 * 1639 * Also verifies that the PTR record is well-formed (e.g., the record data length `GetLength()` matches 1640 * the PTR encoded name). 1641 * 1642 * @param[in] aMessage The message to read from. `aMessage.GetOffset()` MUST point to the start of 1643 * DNS header. 1644 * @param[in,out] aOffset On input, the offset in @p aMessage to start of PTR name field. 1645 * On exit when successfully read, @p aOffset is updated to point to the byte 1646 * after the entire PTR record (skipping over the record). 1647 * @param[out] aNameBuffer A pointer to a char array to output the read name as a null-terminated C string 1648 * (MUST NOT be `nullptr`). 1649 * @param[in] aNameBufferSize The size of @p aNameBuffer. 1650 * 1651 * @retval kErrorNone The PTR name was read successfully. @p aOffset and @p aNameBuffer are updated. 1652 * @retval kErrorParse The PTR record in @p aMessage could not be parsed (invalid format). 1653 * @retval kErrorNoBufs Name could not fit in @p aNameBufferSize chars. 1654 */ ReadPtrName(const Message & aMessage,uint16_t & aOffset,char * aNameBuffer,uint16_t aNameBufferSize) const1655 Error ReadPtrName(const Message &aMessage, uint16_t &aOffset, char *aNameBuffer, uint16_t aNameBufferSize) const 1656 { 1657 return ResourceRecord::ReadName(aMessage, aOffset, /* aStartOffset */ aOffset - sizeof(PtrRecord), aNameBuffer, 1658 aNameBufferSize, 1659 /* aSkipRecord */ true); 1660 } 1661 1662 /** 1663 * Parses and reads the PTR name from a message. 1664 * 1665 * Also verifies that the PTR record is well-formed (e.g., the record data length `GetLength()` matches 1666 * the PTR encoded name). 1667 * 1668 * Unlike the previous method which reads the entire PTR name into a single char buffer, this method reads the 1669 * first label separately and into a different buffer @p aLabelBuffer and the rest of the name into @p aNameBuffer. 1670 * The @p aNameBuffer can be set to `nullptr` if the caller is only interested in the first label. This method is 1671 * intended for "Service Instance Name" where first label (`<Instance>` portion) can be a user-friendly string and 1672 * can contain dot character. 1673 * 1674 * @param[in] aMessage The message to read from. `aMessage.GetOffset()` MUST point to the start of 1675 * DNS header. 1676 * @param[in,out] aOffset On input, the offset in @p aMessage to the start of PTR name field. 1677 * On exit, when successfully read, @p aOffset is updated to point to the byte 1678 * after the entire PTR record (skipping over the record). 1679 * @param[out] aLabelBuffer A pointer to a char array to output the first label as a null-terminated C 1680 * string (MUST NOT be `nullptr`). 1681 * @param[in] aLabelBufferSize The size of @p aLabelBuffer. 1682 * @param[out] aNameBuffer A pointer to a char array to output the rest of name (after first label). Can 1683 * be `nullptr` if caller is only interested in the first label. 1684 * @param[in] aNameBufferSize The size of @p aNameBuffer. 1685 * 1686 * @retval kErrorNone The PTR name was read successfully. @p aOffset, @aLabelBuffer and @aNameBuffer are updated. 1687 * @retval kErrorParse The PTR record in @p aMessage could not be parsed (invalid format). 1688 * @retval kErrorNoBufs Either label or name could not fit in the related char buffers. 1689 */ 1690 Error ReadPtrName(const Message &aMessage, 1691 uint16_t &aOffset, 1692 char *aLabelBuffer, 1693 uint8_t aLabelBufferSize, 1694 char *aNameBuffer, 1695 uint16_t aNameBufferSize) const; 1696 1697 /** 1698 * Parses and reads the PTR name from a message. 1699 * 1700 * This is a template variation of the previous method with name and label buffer sizes as template parameters. 1701 * 1702 * @tparam kLabelBufferSize The size of label buffer. 1703 * @tparam kNameBufferSize The size of name buffer. 1704 * 1705 * @param[in] aMessage The message to read from. `aMessage.GetOffset()` MUST point to the start of 1706 * DNS header. 1707 * @param[in,out] aOffset On input, the offset in @p aMessage to the start of PTR name field. 1708 * On exit, when successfully read, @p aOffset is updated to point to the byte 1709 * after the entire PTR record (skipping over the record). 1710 * @param[out] aLabelBuffer A char array buffer to output the first label as a null-terminated C string. 1711 * @param[out] aNameBuffer A char array to output the rest of name (after first label). 1712 * 1713 * @retval kErrorNone The PTR name was read successfully. @p aOffset, @aLabelBuffer and @aNameBuffer are updated. 1714 * @retval kErrorParse The PTR record in @p aMessage could not be parsed (invalid format). 1715 * @retval kErrorNoBufs Either label or name could not fit in the related given buffers. 1716 */ 1717 template <uint16_t kLabelBufferSize, uint16_t kNameBufferSize> ReadPtrName(const Message & aMessage,uint16_t & aOffset,char (& aLabelBuffer)[kLabelBufferSize],char (& aNameBuffer)[kNameBufferSize]) const1718 Error ReadPtrName(const Message &aMessage, 1719 uint16_t &aOffset, 1720 char (&aLabelBuffer)[kLabelBufferSize], 1721 char (&aNameBuffer)[kNameBufferSize]) const 1722 { 1723 return ReadPtrName(aMessage, aOffset, aLabelBuffer, kLabelBufferSize, aNameBuffer, kNameBufferSize); 1724 } 1725 1726 } OT_TOOL_PACKED_END; 1727 1728 /** 1729 * Implements Resource Record body format of TXT type. 1730 */ 1731 OT_TOOL_PACKED_BEGIN 1732 class TxtRecord : public ResourceRecord 1733 { 1734 public: 1735 static constexpr uint16_t kType = kTypeTxt; ///< The TXT record type. 1736 1737 /** 1738 * Initializes the TXT Resource Record by setting its type and class. 1739 * 1740 * Other record fields (TTL, length) remain unchanged/uninitialized. 1741 * 1742 * @param[in] aClass The class of the resource record (default is `kClassInternet`). 1743 */ Init(uint16_t aClass=kClassInternet)1744 void Init(uint16_t aClass = kClassInternet) { ResourceRecord::Init(kTypeTxt, aClass); } 1745 1746 /** 1747 * Parses and reads the TXT record data from a message. 1748 * 1749 * Also checks if the TXT data is well-formed by calling `VerifyTxtData()` when it is successfully 1750 * read. 1751 * 1752 * @param[in] aMessage The message to read from. 1753 * @param[in,out] aOffset On input, the offset in @p aMessage to start of TXT record data. 1754 * On exit when successfully read, @p aOffset is updated to point to the byte 1755 * after the entire TXT record (skipping over the record). 1756 * @param[out] aTxtBuffer A pointer to a byte array to output the read TXT data. 1757 * @param[in,out] aTxtBufferSize On input, the size of @p aTxtBuffer (max bytes that can be read). 1758 * On exit, @p aTxtBufferSize gives number of bytes written to @p aTxtBuffer. 1759 * 1760 * @retval kErrorNone The TXT data was read successfully. @p aOffset, @p aTxtBuffer and @p aTxtBufferSize 1761 * are updated. 1762 * @retval kErrorParse The TXT record in @p aMessage could not be parsed (invalid format). 1763 * @retval kErrorNoBufs TXT data could not fit in @p aTxtBufferSize bytes. TXT data is still partially read 1764 * into @p aTxtBuffer up to its size and @p aOffset is updated to skip over the full 1765 * TXT record. 1766 */ 1767 Error ReadTxtData(const Message &aMessage, uint16_t &aOffset, uint8_t *aTxtBuffer, uint16_t &aTxtBufferSize) const; 1768 1769 /** 1770 * Tests if a buffer contains valid encoded TXT data. 1771 * 1772 * @param[in] aTxtData The TXT data buffer. 1773 * @param[in] aTxtLength The length of the TXT data buffer. 1774 * @param[in] aAllowEmpty True if zero-length TXT data is allowed. 1775 * 1776 * @returns TRUE if @p aTxtData contains valid encoded TXT data, FALSE if not. 1777 */ 1778 static bool VerifyTxtData(const uint8_t *aTxtData, uint16_t aTxtLength, bool aAllowEmpty); 1779 1780 } OT_TOOL_PACKED_END; 1781 1782 /** 1783 * Implements Resource Record body format of AAAA type. 1784 */ 1785 OT_TOOL_PACKED_BEGIN 1786 class AaaaRecord : public ResourceRecord 1787 { 1788 public: 1789 static constexpr uint16_t kType = kTypeAaaa; ///< The AAAA record type. 1790 1791 /** 1792 * Initializes the AAAA Resource Record by setting its type, class, and length. 1793 * 1794 * Other record fields (TTL, address) remain unchanged/uninitialized. 1795 */ Init(void)1796 void Init(void) 1797 { 1798 ResourceRecord::Init(kTypeAaaa); 1799 SetLength(sizeof(Ip6::Address)); 1800 } 1801 1802 /** 1803 * Tells whether this is a valid AAAA record. 1804 * 1805 * @returns A boolean indicates whether this is a valid AAAA record. 1806 */ 1807 bool IsValid(void) const; 1808 1809 /** 1810 * Sets the IPv6 address of the resource record. 1811 * 1812 * @param[in] aAddress The IPv6 address of the resource record. 1813 */ SetAddress(const Ip6::Address & aAddress)1814 void SetAddress(const Ip6::Address &aAddress) { mAddress = aAddress; } 1815 1816 /** 1817 * Returns the reference to IPv6 address of the resource record. 1818 * 1819 * @returns The reference to IPv6 address of the resource record. 1820 */ GetAddress(void) const1821 const Ip6::Address &GetAddress(void) const { return mAddress; } 1822 1823 private: 1824 Ip6::Address mAddress; // IPv6 Address of AAAA Resource Record. 1825 } OT_TOOL_PACKED_END; 1826 1827 /** 1828 * Implements Resource Record body format of SRV type (RFC 2782). 1829 */ 1830 OT_TOOL_PACKED_BEGIN 1831 class SrvRecord : public ResourceRecord 1832 { 1833 public: 1834 static constexpr uint16_t kType = kTypeSrv; ///< The SRV record type. 1835 1836 /** 1837 * Initializes the SRV Resource Record by settings its type and class. 1838 * 1839 * Other record fields (TTL, length, propriety, weight, port, ...) remain unchanged/uninitialized. 1840 * 1841 * @param[in] aClass The class of the resource record (default is `kClassInternet`). 1842 */ Init(uint16_t aClass=kClassInternet)1843 void Init(uint16_t aClass = kClassInternet) { ResourceRecord::Init(kTypeSrv, aClass); } 1844 1845 /** 1846 * Returns the SRV record's priority value. 1847 * 1848 * @returns The priority value. 1849 */ GetPriority(void) const1850 uint16_t GetPriority(void) const { return BigEndian::HostSwap16(mPriority); } 1851 1852 /** 1853 * Sets the SRV record's priority value. 1854 * 1855 * @param[in] aPriority The priority value. 1856 */ SetPriority(uint16_t aPriority)1857 void SetPriority(uint16_t aPriority) { mPriority = BigEndian::HostSwap16(aPriority); } 1858 1859 /** 1860 * Returns the SRV record's weight value. 1861 * 1862 * @returns The weight value. 1863 */ GetWeight(void) const1864 uint16_t GetWeight(void) const { return BigEndian::HostSwap16(mWeight); } 1865 1866 /** 1867 * Sets the SRV record's weight value. 1868 * 1869 * @param[in] aWeight The weight value. 1870 */ SetWeight(uint16_t aWeight)1871 void SetWeight(uint16_t aWeight) { mWeight = BigEndian::HostSwap16(aWeight); } 1872 1873 /** 1874 * Returns the SRV record's port number on the target host for this service. 1875 * 1876 * @returns The port number. 1877 */ GetPort(void) const1878 uint16_t GetPort(void) const { return BigEndian::HostSwap16(mPort); } 1879 1880 /** 1881 * Sets the SRV record's port number on the target host for this service. 1882 * 1883 * @param[in] aPort The port number. 1884 */ SetPort(uint16_t aPort)1885 void SetPort(uint16_t aPort) { mPort = BigEndian::HostSwap16(aPort); } 1886 1887 /** 1888 * Parses and reads the SRV target host name from a message. 1889 * 1890 * Also verifies that the SRV record is well-formed (e.g., the record data length `GetLength()` matches 1891 * the SRV encoded name). 1892 * 1893 * @param[in] aMessage The message to read from. `aMessage.GetOffset()` MUST point to the start of 1894 * DNS header. 1895 * @param[in,out] aOffset On input, the offset in @p aMessage to start of target host name field. 1896 * On exit when successfully read, @p aOffset is updated to point to the byte 1897 * after the entire SRV record (skipping over the record). 1898 * @param[out] aNameBuffer A pointer to a char array to output the read name as a null-terminated C string 1899 * (MUST NOT be `nullptr`). 1900 * @param[in] aNameBufferSize The size of @p aNameBuffer. 1901 * 1902 * @retval kErrorNone The host name was read successfully. @p aOffset and @p aNameBuffer are updated. 1903 * @retval kErrorParse The SRV record in @p aMessage could not be parsed (invalid format). 1904 * @retval kErrorNoBufs Name could not fit in @p aNameBufferSize chars. 1905 */ ReadTargetHostName(const Message & aMessage,uint16_t & aOffset,char * aNameBuffer,uint16_t aNameBufferSize) const1906 Error ReadTargetHostName(const Message &aMessage, 1907 uint16_t &aOffset, 1908 char *aNameBuffer, 1909 uint16_t aNameBufferSize) const 1910 { 1911 return ResourceRecord::ReadName(aMessage, aOffset, /* aStartOffset */ aOffset - sizeof(SrvRecord), aNameBuffer, 1912 aNameBufferSize, 1913 /* aSkipRecord */ true); 1914 } 1915 1916 /** 1917 * Parses and reads the SRV target host name from a message. 1918 * 1919 * Also verifies that the SRV record is well-formed (e.g., the record data length `GetLength()` matches 1920 * the SRV encoded name). 1921 * 1922 * @tparam kNameBufferSize Size of the name buffer. 1923 * 1924 * @param[in] aMessage The message to read from. `aMessage.GetOffset()` MUST point to the start of 1925 * DNS header. 1926 * @param[in,out] aOffset On input, the offset in @p aMessage to start of target host name field. 1927 * On exit when successfully read, @p aOffset is updated to point to the byte 1928 * after the entire SRV record (skipping over the record). 1929 * @param[out] aNameBuffer A char array to output the read name as a null-terminated C string 1930 * 1931 * @retval kErrorNone The host name was read successfully. @p aOffset and @p aNameBuffer are updated. 1932 * @retval kErrorParse The SRV record in @p aMessage could not be parsed (invalid format). 1933 * @retval kErrorNoBufs Name could not fit in @p aNameBuffer. 1934 */ 1935 template <uint16_t kNameBufferSize> ReadTargetHostName(const Message & aMessage,uint16_t & aOffset,char (& aNameBuffer)[kNameBufferSize]) const1936 Error ReadTargetHostName(const Message &aMessage, uint16_t &aOffset, char (&aNameBuffer)[kNameBufferSize]) const 1937 { 1938 return ReadTargetHostName(aMessage, aOffset, aNameBuffer, kNameBufferSize); 1939 } 1940 1941 private: 1942 uint16_t mPriority; 1943 uint16_t mWeight; 1944 uint16_t mPort; 1945 // Followed by the target host domain name. 1946 1947 } OT_TOOL_PACKED_END; 1948 1949 /** 1950 * Implements Resource Record body format of KEY type (RFC 2535). 1951 */ 1952 OT_TOOL_PACKED_BEGIN 1953 class KeyRecord : public ResourceRecord 1954 { 1955 public: 1956 static constexpr uint16_t kType = kTypeKey; ///< The KEY record type. 1957 1958 // Protocol field values (RFC 2535 - section 3.1.3). 1959 static constexpr uint8_t kProtocolTls = 1; ///< TLS protocol code. 1960 static constexpr uint8_t kProtocolDnsSec = 3; ///< DNS security protocol code. 1961 1962 // Algorithm field values (RFC 8624 - section 3.1). 1963 static constexpr uint8_t kAlgorithmEcdsaP256Sha256 = 13; ///< ECDSA-P256-SHA256 algorithm. 1964 static constexpr uint8_t kAlgorithmEcdsaP384Sha384 = 14; ///< ECDSA-P384-SHA384 algorithm. 1965 static constexpr uint8_t kAlgorithmEd25519 = 15; ///< ED25519 algorithm. 1966 static constexpr uint8_t kAlgorithmEd448 = 16; ///< ED448 algorithm. 1967 1968 /** 1969 * Type represents the use (or key type) flags (RFC 2535 - section 3.1.2). 1970 */ 1971 enum UseFlags : uint8_t 1972 { 1973 kAuthConfidPermitted = 0x00, ///< Use of the key for authentication and/or confidentiality is permitted. 1974 kAuthPermitted = 0x40, ///< Use of the key is only permitted for authentication. 1975 kConfidPermitted = 0x80, ///< Use of the key is only permitted for confidentiality. 1976 kNoKey = 0xc0, ///< No key value (e.g., can indicate zone is not secure). 1977 }; 1978 1979 /** 1980 * Type represents key owner (or name type) flags (RFC 2535 - section 3.1.2). 1981 */ 1982 enum OwnerFlags : uint8_t 1983 { 1984 kOwnerUser = 0x00, ///< Key is associated with a "user" or "account" at end entity. 1985 kOwnerZone = 0x01, ///< Key is a zone key (used for data origin authentication). 1986 kOwnerNonZone = 0x02, ///< Key is associated with a non-zone "entity". 1987 kOwnerReserved = 0x03, ///< Reserved for future use. 1988 }; 1989 1990 // Constants for flag bits for the "signatory" flags (RFC 2137). 1991 // 1992 // The flags defined are for non-zone (`kOwnerNoneZone`) keys (RFC 2137 - section 3.1.3). 1993 1994 /** 1995 * Key is authorized to attach, detach, and move zones. 1996 */ 1997 static constexpr uint8_t kSignatoryFlagZone = 1 << 3; 1998 1999 /** 2000 * Key is authorized to add and delete RRs even if RRs auth with other key. 2001 */ 2002 static constexpr uint8_t kSignatoryFlagStrong = 1 << 2; 2003 2004 /** 2005 * Key is authorized to add and update RRs for only a single owner name. 2006 */ 2007 static constexpr uint8_t kSignatoryFlagUnique = 1 << 1; 2008 2009 /** 2010 * If the other flags are zero, this is used to indicate it is an update key. 2011 */ 2012 static constexpr uint8_t kSignatoryFlagGeneral = 1 << 0; 2013 2014 /** 2015 * Initializes the KEY Resource Record by setting its type and class. 2016 * 2017 * Other record fields (TTL, length, flags, protocol, algorithm) remain unchanged/uninitialized. 2018 * 2019 * @param[in] aClass The class of the resource record (default is `kClassInternet`). 2020 */ Init(uint16_t aClass=kClassInternet)2021 void Init(uint16_t aClass = kClassInternet) { ResourceRecord::Init(kTypeKey, aClass); } 2022 2023 /** 2024 * Tells whether the KEY record is valid. 2025 * 2026 * @returns TRUE if this is a valid KEY record, FALSE if an invalid KEY record. 2027 */ 2028 bool IsValid(void) const; 2029 2030 /** 2031 * Gets the key use (or key type) flags. 2032 * 2033 * @returns The key use flags. 2034 */ GetUseFlags(void) const2035 UseFlags GetUseFlags(void) const { return static_cast<UseFlags>(mFlags[0] & kUseFlagsMask); } 2036 2037 /** 2038 * Gets the owner (or name type) flags. 2039 * 2040 * @returns The key owner flags. 2041 */ GetOwnerFlags(void) const2042 OwnerFlags GetOwnerFlags(void) const { return static_cast<OwnerFlags>(mFlags[0] & kOwnerFlagsMask); } 2043 2044 /** 2045 * Gets the signatory flags. 2046 * 2047 * @returns The signatory flags. 2048 */ GetSignatoryFlags(void) const2049 uint8_t GetSignatoryFlags(void) const { return (mFlags[1] & kSignatoryFlagsMask); } 2050 2051 /** 2052 * Sets the flags field. 2053 * 2054 * @param[in] aUseFlags The `UseFlags` value. 2055 * @param[in] aOwnerFlags The `OwnerFlags` value. 2056 * @param[in] aSignatoryFlags The signatory flags. 2057 */ SetFlags(UseFlags aUseFlags,OwnerFlags aOwnerFlags,uint8_t aSignatoryFlags)2058 void SetFlags(UseFlags aUseFlags, OwnerFlags aOwnerFlags, uint8_t aSignatoryFlags) 2059 { 2060 mFlags[0] = (static_cast<uint8_t>(aUseFlags) | static_cast<uint8_t>(aOwnerFlags)); 2061 mFlags[1] = (aSignatoryFlags & kSignatoryFlagsMask); 2062 } 2063 2064 /** 2065 * Returns the KEY record's protocol value. 2066 * 2067 * @returns The protocol value. 2068 */ GetProtocol(void) const2069 uint8_t GetProtocol(void) const { return mProtocol; } 2070 2071 /** 2072 * Sets the KEY record's protocol value. 2073 * 2074 * @param[in] aProtocol The protocol value. 2075 */ SetProtocol(uint8_t aProtocol)2076 void SetProtocol(uint8_t aProtocol) { mProtocol = aProtocol; } 2077 2078 /** 2079 * Returns the KEY record's algorithm value. 2080 * 2081 * @returns The algorithm value. 2082 */ GetAlgorithm(void) const2083 uint8_t GetAlgorithm(void) const { return mAlgorithm; } 2084 2085 /** 2086 * Sets the KEY record's algorithm value. 2087 * 2088 * @param[in] aAlgorithm The algorithm value. 2089 */ SetAlgorithm(uint8_t aAlgorithm)2090 void SetAlgorithm(uint8_t aAlgorithm) { mAlgorithm = aAlgorithm; } 2091 2092 private: 2093 static constexpr uint8_t kUseFlagsMask = 0xc0; // top two bits in the first flag byte. 2094 static constexpr uint8_t kOwnerFlagsMask = 0x03; // lowest two bits in the first flag byte. 2095 static constexpr uint8_t kSignatoryFlagsMask = 0x0f; // lower 4 bits in the second flag byte. 2096 2097 // Flags format: 2098 // 2099 // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 2100 // +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ 2101 // | Use | Z | XT| Z | Z | Owner | Z | Z | Z | Z | SIG | 2102 // +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ 2103 // \ / \ / 2104 // ---------- mFlags[0] --------- -------- mFlags[1] ---------- 2105 2106 uint8_t mFlags[2]; 2107 uint8_t mProtocol; 2108 uint8_t mAlgorithm; 2109 // Followed by the public key 2110 2111 } OT_TOOL_PACKED_END; 2112 2113 #if OPENTHREAD_CONFIG_SRP_SERVER_ENABLE 2114 OT_TOOL_PACKED_BEGIN 2115 class Ecdsa256KeyRecord : public KeyRecord, public Clearable<Ecdsa256KeyRecord>, public Equatable<Ecdsa256KeyRecord> 2116 { 2117 public: 2118 /** 2119 * Initializes the KEY Resource Record to ECDSA with curve P-256. 2120 * 2121 * Other record fields (TTL, length, flags, protocol) remain unchanged/uninitialized. 2122 */ 2123 void Init(void); 2124 2125 /** 2126 * Tells whether this is a valid ECDSA DNSKEY with curve P-256. 2127 * 2128 * @returns A boolean that indicates whether this is a valid ECDSA DNSKEY RR with curve P-256. 2129 */ 2130 bool IsValid(void) const; 2131 2132 /** 2133 * Returns the ECDSA P-256 public key. 2134 * 2135 * @returns A reference to the public key. 2136 */ GetKey(void) const2137 const Crypto::Ecdsa::P256::PublicKey &GetKey(void) const { return mKey; } 2138 2139 /** 2140 * Sets the ECDSA P-256 public key. 2141 * 2142 * @param[in] aKey The public key. 2143 */ SetKey(const Crypto::Ecdsa::P256::PublicKey & aKey)2144 void SetKey(const Crypto::Ecdsa::P256::PublicKey &aKey) { mKey = aKey; } 2145 2146 private: 2147 Crypto::Ecdsa::P256::PublicKey mKey; 2148 } OT_TOOL_PACKED_END; 2149 #endif // OPENTHREAD_CONFIG_SRP_SERVER_ENABLE 2150 2151 /** 2152 * Implements Resource Record body format of SIG type (RFC 2535 - section-4.1). 2153 */ 2154 OT_TOOL_PACKED_BEGIN 2155 class SigRecord : public ResourceRecord, public Clearable<SigRecord> 2156 { 2157 public: 2158 static constexpr uint16_t kType = kTypeSig; ///< The SIG record type. 2159 2160 /** 2161 * Initializes the SIG Resource Record by setting its type and class. 2162 * 2163 * Other record fields (TTL, length, ...) remain unchanged/uninitialized. 2164 * 2165 * SIG(0) requires SIG RR to set class field as ANY or `kClassAny` (RFC 2931 - section 3). 2166 * 2167 * @param[in] aClass The class of the resource record. 2168 */ Init(uint16_t aClass)2169 void Init(uint16_t aClass) { ResourceRecord::Init(kTypeSig, aClass); } 2170 2171 /** 2172 * Tells whether the SIG record is valid. 2173 * 2174 * @returns TRUE if this is a valid SIG record, FALSE if not a valid SIG record. 2175 */ 2176 bool IsValid(void) const; 2177 2178 /** 2179 * Returns the SIG record's type-covered value. 2180 * 2181 * @returns The type-covered value. 2182 */ GetTypeCovered(void) const2183 uint16_t GetTypeCovered(void) const { return BigEndian::HostSwap16(mTypeCovered); } 2184 2185 /** 2186 * Sets the SIG record's type-covered value. 2187 * 2188 * @param[in] aTypeCovered The type-covered value. 2189 */ SetTypeCovered(uint8_t aTypeCovered)2190 void SetTypeCovered(uint8_t aTypeCovered) { mTypeCovered = BigEndian::HostSwap16(aTypeCovered); } 2191 2192 /** 2193 * Returns the SIG record's algorithm value. 2194 * 2195 * @returns The algorithm value. 2196 */ GetAlgorithm(void) const2197 uint8_t GetAlgorithm(void) const { return mAlgorithm; } 2198 2199 /** 2200 * Sets the SIG record's algorithm value. 2201 * 2202 * @param[in] aAlgorithm The algorithm value. 2203 */ SetAlgorithm(uint8_t aAlgorithm)2204 void SetAlgorithm(uint8_t aAlgorithm) { mAlgorithm = aAlgorithm; } 2205 2206 /** 2207 * Returns the SIG record's labels-count (number of labels, not counting null label, in the original 2208 * name of the owner). 2209 * 2210 * @returns The labels-count value. 2211 */ GetLabels(void) const2212 uint8_t GetLabels(void) const { return mLabels; } 2213 2214 /** 2215 * Sets the SIG record's labels-count (number of labels, not counting null label, in the original 2216 * name of the owner). 2217 * 2218 * @param[in] aLabels The labels-count value. 2219 */ SetLabels(uint8_t aLabels)2220 void SetLabels(uint8_t aLabels) { mLabels = aLabels; } 2221 2222 /** 2223 * Returns the SIG record's original TTL value. 2224 * 2225 * @returns The original TTL value. 2226 */ GetOriginalTtl(void) const2227 uint32_t GetOriginalTtl(void) const { return BigEndian::HostSwap32(mOriginalTtl); } 2228 2229 /** 2230 * Sets the SIG record's original TTL value. 2231 * 2232 * @param[in] aOriginalTtl The original TTL value. 2233 */ SetOriginalTtl(uint32_t aOriginalTtl)2234 void SetOriginalTtl(uint32_t aOriginalTtl) { mOriginalTtl = BigEndian::HostSwap32(aOriginalTtl); } 2235 2236 /** 2237 * Returns the SIG record's expiration time value. 2238 * 2239 * @returns The expiration time value (seconds since Jan 1, 1970). 2240 */ GetExpiration(void) const2241 uint32_t GetExpiration(void) const { return BigEndian::HostSwap32(mExpiration); } 2242 2243 /** 2244 * Sets the SIG record's expiration time value. 2245 * 2246 * @param[in] aExpiration The expiration time value (seconds since Jan 1, 1970). 2247 */ SetExpiration(uint32_t aExpiration)2248 void SetExpiration(uint32_t aExpiration) { mExpiration = BigEndian::HostSwap32(aExpiration); } 2249 2250 /** 2251 * Returns the SIG record's inception time value. 2252 * 2253 * @returns The inception time value (seconds since Jan 1, 1970). 2254 */ GetInception(void) const2255 uint32_t GetInception(void) const { return BigEndian::HostSwap32(mInception); } 2256 2257 /** 2258 * Sets the SIG record's inception time value. 2259 * 2260 * @param[in] aInception The inception time value (seconds since Jan 1, 1970). 2261 */ SetInception(uint32_t aInception)2262 void SetInception(uint32_t aInception) { mInception = BigEndian::HostSwap32(aInception); } 2263 2264 /** 2265 * Returns the SIG record's key tag value. 2266 * 2267 * @returns The key tag value. 2268 */ GetKeyTag(void) const2269 uint16_t GetKeyTag(void) const { return BigEndian::HostSwap16(mKeyTag); } 2270 2271 /** 2272 * Sets the SIG record's key tag value. 2273 * 2274 * @param[in] aKeyTag The key tag value. 2275 */ SetKeyTag(uint16_t aKeyTag)2276 void SetKeyTag(uint16_t aKeyTag) { mKeyTag = BigEndian::HostSwap16(aKeyTag); } 2277 2278 /** 2279 * Returns a pointer to the start of the record data fields. 2280 * 2281 * @returns A pointer to the start of the record data fields. 2282 */ GetRecordData(void) const2283 const uint8_t *GetRecordData(void) const { return reinterpret_cast<const uint8_t *>(&mTypeCovered); } 2284 2285 /** 2286 * Parses and reads the SIG signer name from a message. 2287 * 2288 * @param[in] aMessage The message to read from. `aMessage.GetOffset()` MUST point to the start of DNS 2289 * header. 2290 * @param[in,out] aOffset On input, the offset in @p aMessage to start of signer name field. 2291 * On exit when successfully read, @p aOffset is updated to point to the byte 2292 * after the name field (i.e., start of signature field). 2293 * @param[out] aNameBuffer A pointer to a char array to output the read name as a null-terminated C string 2294 * (MUST NOT be `nullptr`). 2295 * @param[in] aNameBufferSize The size of @p aNameBuffer. 2296 * 2297 * @retval kErrorNone The name was read successfully. @p aOffset and @p aNameBuffer are updated. 2298 * @retval kErrorParse The SIG record in @p aMessage could not be parsed (invalid format). 2299 * @retval kErrorNoBufs Name could not fit in @p aNameBufferSize chars. 2300 */ ReadSignerName(const Message & aMessage,uint16_t & aOffset,char * aNameBuffer,uint16_t aNameBufferSize) const2301 Error ReadSignerName(const Message &aMessage, uint16_t &aOffset, char *aNameBuffer, uint16_t aNameBufferSize) const 2302 { 2303 return ResourceRecord::ReadName(aMessage, aOffset, /* aStartOffset */ aOffset - sizeof(SigRecord), aNameBuffer, 2304 aNameBufferSize, 2305 /* aSkipRecord */ false); 2306 } 2307 2308 private: 2309 uint16_t mTypeCovered; // type of the other RRs covered by this SIG. set to zero for SIG(0). 2310 uint8_t mAlgorithm; // Algorithm number (see `KeyRecord` enumeration). 2311 uint8_t mLabels; // Number of labels (not counting null label) in the original name of the owner of RR. 2312 uint32_t mOriginalTtl; // Original time-to-live (should set to zero for SIG(0)). 2313 uint32_t mExpiration; // Signature expiration time (seconds since Jan 1, 1970). 2314 uint32_t mInception; // Signature inception time (seconds since Jan 1, 1970). 2315 uint16_t mKeyTag; // Key tag. 2316 // Followed by signer name fields and signature fields 2317 } OT_TOOL_PACKED_END; 2318 2319 /** 2320 * Implements DNS OPT Pseudo Resource Record header for EDNS(0) (RFC 6891 - Section 6.1). 2321 */ 2322 OT_TOOL_PACKED_BEGIN 2323 class OptRecord : public ResourceRecord 2324 { 2325 public: 2326 static constexpr uint16_t kType = kTypeOpt; ///< The OPT record type. 2327 2328 /** 2329 * Initializes the OPT Resource Record by setting its type and clearing extended Response Code, version 2330 * and all flags. 2331 * 2332 * Other record fields (UDP payload size, length) remain unchanged/uninitialized. 2333 */ Init(void)2334 void Init(void) 2335 { 2336 SetType(kTypeOpt); 2337 SetTtl(0); 2338 } 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 * The field is encoded in the CLASS field. 2345 * 2346 * @returns The UDP payload size. 2347 */ GetUdpPayloadSize(void) const2348 uint16_t GetUdpPayloadSize(void) const { return GetClass(); } 2349 2350 /** 2351 * Gets the requester's UDP payload size (the number of bytes of the largest UDP payload that can be 2352 * delivered in the requester's network). 2353 * 2354 * @param[in] aPayloadSize The UDP payload size. 2355 */ SetUdpPayloadSize(uint16_t aPayloadSize)2356 void SetUdpPayloadSize(uint16_t aPayloadSize) { SetClass(aPayloadSize); } 2357 2358 /** 2359 * Gets the upper 8-bit of the extended 12-bit Response Code. 2360 * 2361 * Value of 0 indicates that an unextended Response code is in use. 2362 * 2363 * @return The upper 8-bit of the extended 12-bit Response Code. 2364 */ GetExtendedResponseCode(void) const2365 uint8_t GetExtendedResponseCode(void) const { return GetTtlByteAt(kExtRCodeByteIndex); } 2366 2367 /** 2368 * Sets the upper 8-bit of the extended 12-bit Response Code. 2369 * 2370 * Value of 0 indicates that an unextended Response code is in use. 2371 * 2372 * @param[in] aExtendedResponse The upper 8-bit of the extended 12-bit Response Code. 2373 */ SetExtendedResponseCode(uint8_t aExtendedResponse)2374 void SetExtendedResponseCode(uint8_t aExtendedResponse) { GetTtlByteAt(kExtRCodeByteIndex) = aExtendedResponse; } 2375 2376 /** 2377 * Gets the Version field. 2378 * 2379 * @returns The version. 2380 */ GetVersion(void) const2381 uint8_t GetVersion(void) const { return GetTtlByteAt(kVersionByteIndex); } 2382 2383 /** 2384 * Set the Version field. 2385 * 2386 * @param[in] aVersion The version. 2387 */ SetVersion(uint8_t aVersion)2388 void SetVersion(uint8_t aVersion) { GetTtlByteAt(kVersionByteIndex) = aVersion; } 2389 2390 /** 2391 * Indicates whether the DNSSEC OK flag is set or not. 2392 * 2393 * @returns True if DNSSEC OK flag is set in the header, false otherwise. 2394 */ IsDnsSecurityFlagSet(void) const2395 bool IsDnsSecurityFlagSet(void) const { return (GetTtlByteAt(kFlagByteIndex) & kDnsSecFlag) != 0; } 2396 2397 /** 2398 * Clears the DNSSEC OK bit flag. 2399 */ ClearDnsSecurityFlag(void)2400 void ClearDnsSecurityFlag(void) { GetTtlByteAt(kFlagByteIndex) &= ~kDnsSecFlag; } 2401 2402 /** 2403 * Sets the DNSSEC OK bit flag. 2404 */ SetDnsSecurityFlag(void)2405 void SetDnsSecurityFlag(void) { GetTtlByteAt(kFlagByteIndex) |= kDnsSecFlag; } 2406 2407 private: 2408 // The OPT RR re-purposes the existing CLASS and TTL fields in the 2409 // RR. The CLASS field (`uint16_t`) is used for requester UDP 2410 // payload size. The TTL field is used for extended Response Code, 2411 // version and flags as follows: 2412 // 2413 // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 2414 // +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ 2415 // | EXTENDED-RCODE | VERSION | 2416 // +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ 2417 // | DO| Z | Z | 2418 // +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ 2419 // 2420 // The variable data part of OPT RR can contain zero of more `Option`. 2421 2422 static constexpr uint8_t kExtRCodeByteIndex = 0; // Byte index of Extended RCODE within the TTL field. 2423 static constexpr uint8_t kVersionByteIndex = 1; // Byte index of Version within the TTL field. 2424 static constexpr uint8_t kFlagByteIndex = 2; // Byte index of flag byte within the TTL field. 2425 static constexpr uint8_t kDnsSecFlag = 1 << 7; // DNSSec OK bit flag. 2426 GetTtlByteAt(uint8_t aIndex) const2427 uint8_t GetTtlByteAt(uint8_t aIndex) const { return reinterpret_cast<const uint8_t *>(&mTtl)[aIndex]; } GetTtlByteAt(uint8_t aIndex)2428 uint8_t &GetTtlByteAt(uint8_t aIndex) { return reinterpret_cast<uint8_t *>(&mTtl)[aIndex]; } 2429 2430 } OT_TOOL_PACKED_END; 2431 2432 /** 2433 * Implements the body of an Option in OPT Pseudo Resource Record (RFC 6981 - Section 6.1). 2434 */ 2435 OT_TOOL_PACKED_BEGIN 2436 class Option 2437 { 2438 public: 2439 static constexpr uint16_t kUpdateLease = 2; ///< Update lease option code. 2440 2441 /** 2442 * Returns the option code value. 2443 * 2444 * @returns The option code value. 2445 */ GetOptionCode(void) const2446 uint16_t GetOptionCode(void) const { return BigEndian::HostSwap16(mOptionCode); } 2447 2448 /** 2449 * Sets the option code value. 2450 * 2451 * @param[in] aOptionCode The option code value. 2452 */ SetOptionCode(uint16_t aOptionCode)2453 void SetOptionCode(uint16_t aOptionCode) { mOptionCode = BigEndian::HostSwap16(aOptionCode); } 2454 2455 /** 2456 * Returns the option length value. 2457 * 2458 * @returns The option length (size of option data in bytes). 2459 */ GetOptionLength(void) const2460 uint16_t GetOptionLength(void) const { return BigEndian::HostSwap16(mOptionLength); } 2461 2462 /** 2463 * Sets the option length value. 2464 * 2465 * @param[in] aOptionLength The option length (size of option data in bytes). 2466 */ SetOptionLength(uint16_t aOptionLength)2467 void SetOptionLength(uint16_t aOptionLength) { mOptionLength = BigEndian::HostSwap16(aOptionLength); } 2468 2469 /** 2470 * Returns the size of (number of bytes) in the Option and its data. 2471 * 2472 * @returns Size (number of bytes) of the Option its data section. 2473 */ GetSize(void) const2474 uint32_t GetSize(void) const { return sizeof(Option) + GetOptionLength(); } 2475 2476 private: 2477 uint16_t mOptionCode; 2478 uint16_t mOptionLength; 2479 // Followed by Option data (varies per option code). 2480 2481 } OT_TOOL_PACKED_END; 2482 2483 /** 2484 * Implements an Update Lease Option body. 2485 * 2486 * This implementation is intended for use in Dynamic DNS Update Lease Requests and Responses as specified in 2487 * https://tools.ietf.org/html/draft-sekar-dns-ul-02. 2488 */ 2489 OT_TOOL_PACKED_BEGIN 2490 class LeaseOption : public Option 2491 { 2492 public: 2493 /** 2494 * Initializes the Update Lease Option using the short variant format which contains lease interval 2495 * only. 2496 * 2497 * @param[in] aLeaseInterval The lease interval in seconds. 2498 */ 2499 void InitAsShortVariant(uint32_t aLeaseInterval); 2500 2501 /** 2502 * Initializes the Update Lease Option using the long variant format which contains both lease and 2503 * key lease intervals. 2504 * 2505 * @param[in] aLeaseInterval The lease interval in seconds. 2506 * @param[in] aKeyLeaseInterval The key lease interval in seconds. 2507 */ 2508 void InitAsLongVariant(uint32_t aLeaseInterval, uint32_t aKeyLeaseInterval); 2509 2510 /** 2511 * Indicates whether or not the Update Lease Option follows the short variant format which contains 2512 * only the lease interval. 2513 * 2514 * @retval TRUE The Update Lease Option follows the short variant format. 2515 * @retval FALSE The Update Lease Option follows the long variant format. 2516 */ IsShortVariant(void) const2517 bool IsShortVariant(void) const { return (GetOptionLength() == kShortLength); } 2518 2519 /** 2520 * Tells whether this is a valid Lease Option. 2521 * 2522 * Validates that option follows either short or long variant format. 2523 * 2524 * @returns TRUE if this is a valid Lease Option, FALSE if not a valid Lease Option. 2525 */ 2526 bool IsValid(void) const; 2527 2528 /** 2529 * Returns the Update Lease OPT record's lease interval value. 2530 * 2531 * @returns The lease interval value (in seconds). 2532 */ GetLeaseInterval(void) const2533 uint32_t GetLeaseInterval(void) const { return BigEndian::HostSwap32(mLeaseInterval); } 2534 2535 /** 2536 * Returns the Update Lease OPT record's key lease interval value. 2537 * 2538 * If the Update Lease Option follows the short variant format the lease interval is returned as key lease interval. 2539 * 2540 * @returns The key lease interval value (in seconds). 2541 */ GetKeyLeaseInterval(void) const2542 uint32_t GetKeyLeaseInterval(void) const 2543 { 2544 return IsShortVariant() ? GetLeaseInterval() : BigEndian::HostSwap32(mKeyLeaseInterval); 2545 } 2546 2547 /** 2548 * Searches among the Options is a given message and reads and validates the Update Lease Option if 2549 * found. 2550 * 2551 * Reads the Update Lease Option whether it follows the short or long variant formats. 2552 * 2553 * @param[in] aMessage The message to read the Option from. 2554 * @param[in] aOffset Offset in @p aMessage to the start of Options (start of OPT Record data). 2555 * @param[in] aLength Length of Option data in OPT record. 2556 * 2557 * @retval kErrorNone Successfully read and validated the Update Lease Option from @p aMessage. 2558 * @retval kErrorNotFound Did not find any Update Lease Option. 2559 * @retval kErrorParse Failed to parse the Options. 2560 */ 2561 Error ReadFrom(const Message &aMessage, uint16_t aOffset, uint16_t aLength); 2562 2563 private: 2564 static constexpr uint16_t kShortLength = sizeof(uint32_t); // lease only. 2565 static constexpr uint16_t kLongLength = sizeof(uint32_t) + sizeof(uint32_t); // lease and key lease values 2566 SetLeaseInterval(uint32_t aLeaseInterval)2567 void SetLeaseInterval(uint32_t aLeaseInterval) { mLeaseInterval = BigEndian::HostSwap32(aLeaseInterval); } SetKeyLeaseInterval(uint32_t aKeyLeaseInterval)2568 void SetKeyLeaseInterval(uint32_t aKeyLeaseInterval) 2569 { 2570 mKeyLeaseInterval = BigEndian::HostSwap32(aKeyLeaseInterval); 2571 } 2572 2573 uint32_t mLeaseInterval; 2574 uint32_t mKeyLeaseInterval; 2575 } OT_TOOL_PACKED_END; 2576 2577 /** 2578 * Implements body format of NSEC record (RFC 3845) for use with mDNS. 2579 */ 2580 OT_TOOL_PACKED_BEGIN 2581 class NsecRecord : public ResourceRecord 2582 { 2583 public: 2584 static constexpr uint16_t kType = kTypeNsec; ///< The NSEC record type. 2585 2586 /** 2587 * Represents NSEC Type Bit Map field (RFC 3845 - section 2.1.2) 2588 */ 2589 OT_TOOL_PACKED_BEGIN 2590 class TypeBitMap : public Clearable<TypeBitMap> 2591 { 2592 public: 2593 static constexpr uint8_t kMinSize = 2; ///< Minimum size of a valid `TypeBitMap` (with zero length). 2594 2595 static constexpr uint8_t kMaxLength = 32; ///< Maximum BitmapLength value. 2596 2597 /** 2598 * Gets the Window Block Number 2599 * 2600 * @returns The Window Block Number. 2601 */ GetBlockNumber(void) const2602 uint8_t GetBlockNumber(void) const { return mBlockNumber; } 2603 2604 /** 2605 * Sets the Window Block Number 2606 * 2607 * @param[in] aBlockNumber The Window Block Number. 2608 */ SetBlockNumber(uint8_t aBlockNumber)2609 void SetBlockNumber(uint8_t aBlockNumber) { mBlockNumber = aBlockNumber; } 2610 2611 /** 2612 * Gets the Bitmap length 2613 * 2614 * @returns The Bitmap length 2615 */ GetBitmapLength(void)2616 uint8_t GetBitmapLength(void) { return mBitmapLength; } 2617 2618 /** 2619 * Gets the total size (number of bytes) of the `TypeBitMap` field. 2620 * 2621 * @returns The size of the `TypeBitMap` 2622 */ GetSize(void) const2623 uint16_t GetSize(void) const { return (sizeof(mBlockNumber) + sizeof(mBitmapLength) + mBitmapLength); } 2624 2625 /** 2626 * Adds a resource record type to the Bitmap. 2627 * 2628 * As the types are added to the Bitmap the Bitmap length gets updated accordingly. 2629 * 2630 * The type space is split into 256 window blocks, each representing the low-order 8 bits of the 16-bit type 2631 * value. If @p aType does not match the currently set Window Block Number, no action is performed. 2632 * 2633 * @param[in] aType The resource record type to add. 2634 */ 2635 void AddType(uint16_t aType); 2636 2637 /** 2638 * Indicates whether a given resource record type is present in the Bitmap. 2639 * 2640 * If @p aType does not match the currently set Window Block Number, this method returns `false`.. 2641 * 2642 * @param[in] aType The resource record type to check. 2643 * 2644 * @retval TRUE The @p aType is present in the Bitmap. 2645 * @retval FALSE The @p aType is not present in the Bitmap. 2646 */ 2647 bool ContainsType(uint16_t aType) const; 2648 2649 private: 2650 uint8_t mBlockNumber; 2651 uint8_t mBitmapLength; 2652 uint8_t mBitmaps[kMaxLength]; 2653 } OT_TOOL_PACKED_END; 2654 2655 /** 2656 * Initializes the NSEC Resource Record by setting its type and class. 2657 * 2658 * Other record fields (TTL, length remain unchanged/uninitialized. 2659 * 2660 * @param[in] aClass The class of the resource record (default is `kClassInternet`). 2661 */ Init(uint16_t aClass=kClassInternet)2662 void Init(uint16_t aClass = kClassInternet) { ResourceRecord::Init(kTypeNsec, aClass); } 2663 2664 } OT_TOOL_PACKED_END; 2665 2666 /** 2667 * Implements Question format. 2668 */ 2669 OT_TOOL_PACKED_BEGIN 2670 class Question 2671 { 2672 public: 2673 /** 2674 * Default constructor for Question 2675 */ 2676 Question(void) = default; 2677 2678 /** 2679 * Constructor for Question. 2680 */ Question(uint16_t aType,uint16_t aClass=ResourceRecord::kClassInternet)2681 explicit Question(uint16_t aType, uint16_t aClass = ResourceRecord::kClassInternet) 2682 { 2683 SetType(aType); 2684 SetClass(aClass); 2685 } 2686 2687 /** 2688 * Returns the type of the question. 2689 * 2690 * @returns The type of the question. 2691 */ GetType(void) const2692 uint16_t GetType(void) const { return BigEndian::HostSwap16(mType); } 2693 2694 /** 2695 * Sets the type of the question. 2696 * 2697 * @param[in] aType The type of the question. 2698 */ SetType(uint16_t aType)2699 void SetType(uint16_t aType) { mType = BigEndian::HostSwap16(aType); } 2700 2701 /** 2702 * Returns the class of the question. 2703 * 2704 * @returns The class of the question. 2705 */ GetClass(void) const2706 uint16_t GetClass(void) const { return BigEndian::HostSwap16(mClass); } 2707 2708 /** 2709 * Sets the class of the question. 2710 * 2711 * @param[in] aClass The class of the question. 2712 */ SetClass(uint16_t aClass)2713 void SetClass(uint16_t aClass) { mClass = BigEndian::HostSwap16(aClass); } 2714 2715 private: 2716 uint16_t mType; // The type of the data in question section. 2717 uint16_t mClass; // The class of the data in question section. 2718 } OT_TOOL_PACKED_END; 2719 2720 /** 2721 * Implements Zone section body for DNS Update (RFC 2136 - section 2.3). 2722 */ 2723 OT_TOOL_PACKED_BEGIN 2724 class Zone : public Question 2725 { 2726 public: 2727 /** 2728 * Constructor for Zone. 2729 * 2730 * @param[in] aClass The class of the zone (default is `kClassInternet`). 2731 */ Zone(uint16_t aClass=ResourceRecord::kClassInternet)2732 explicit Zone(uint16_t aClass = ResourceRecord::kClassInternet) 2733 : Question(ResourceRecord::kTypeSoa, aClass) 2734 { 2735 } 2736 } OT_TOOL_PACKED_END; 2737 2738 /** 2739 * @} 2740 */ 2741 2742 } // namespace Dns 2743 2744 DefineCoreType(otDnsTxtEntry, Dns::TxtEntry); 2745 DefineCoreType(otDnsTxtEntryIterator, Dns::TxtEntry::Iterator); 2746 2747 } // namespace ot 2748 2749 #endif // DNS_HEADER_HPP_ 2750