1 /* 2 * Copyright (c) 2016, 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 DHCPv6 Service. 32 */ 33 34 #ifndef DHCP6_HPP_ 35 #define DHCP6_HPP_ 36 37 #include "openthread-core-config.h" 38 39 #if OPENTHREAD_CONFIG_DHCP6_SERVER_ENABLE || OPENTHREAD_CONFIG_DHCP6_CLIENT_ENABLE 40 41 #include "common/clearable.hpp" 42 #include "common/equatable.hpp" 43 #include "common/message.hpp" 44 #include "common/random.hpp" 45 #include "mac/mac_types.hpp" 46 #include "net/udp6.hpp" 47 48 namespace ot { 49 namespace Dhcp6 { 50 51 /** 52 * @addtogroup core-dhcp6 53 * 54 * @brief 55 * This module includes definitions for DHCPv6. 56 * 57 * @{ 58 * 59 */ 60 61 constexpr uint16_t kDhcpClientPort = 546; 62 constexpr uint16_t kDhcpServerPort = 547; 63 constexpr uint16_t kHardwareTypeEui64 = 27; 64 constexpr uint16_t kHardwareTypeEthernet = 1; 65 66 /** 67 * DHCPv6 Message Types 68 * 69 */ 70 enum Type : uint8_t 71 { 72 kTypeNone = 0, 73 kTypeSolicit = 1, 74 kTypeAdvertise = 2, 75 kTypeRequest = 3, 76 kTypeConfirm = 4, 77 kTypeRenew = 5, 78 kTypeRebind = 6, 79 kTypeReply = 7, 80 kTypeRelease = 8, 81 kTypeDecline = 9, 82 kTypeReconfigure = 10, 83 kTypeInformationRequest = 11, 84 kTypeRelayForward = 12, 85 kTypeRelayReply = 13, 86 kTypeLeaseQuery = 14, 87 kTypeLeaseQueryReply = 15, 88 }; 89 90 /** 91 * Represents a DHCP6 transaction identifier. 92 * 93 */ 94 OT_TOOL_PACKED_BEGIN 95 class TransactionId : public Equatable<TransactionId>, public Clearable<TransactionId> 96 { 97 public: 98 static constexpr uint16_t kSize = 3; ///< Transaction Id size (in bytes). 99 100 /** 101 * Generates a cryptographically secure random sequence to populate the transaction identifier. 102 * 103 * @retval kErrorNone Successfully generated a random transaction identifier. 104 * @retval kErrorFailed Failed to generate random sequence. 105 * 106 */ GenerateRandom(void)107 Error GenerateRandom(void) 108 { 109 OT_UNUSED_VARIABLE(m8); 110 111 return Random::Crypto::Fill(*this); 112 } 113 114 private: 115 uint8_t m8[kSize]; 116 } OT_TOOL_PACKED_END; 117 118 /** 119 * Implements DHCPv6 header. 120 * 121 */ 122 OT_TOOL_PACKED_BEGIN 123 class Header : public Clearable<Header> 124 { 125 public: 126 /** 127 * Returns the DHCPv6 message type. 128 * 129 * @returns The DHCPv6 message type. 130 * 131 */ GetType(void) const132 Type GetType(void) const { return mType; } 133 134 /** 135 * Sets the DHCPv6 message type. 136 * 137 * @param[in] aType The DHCPv6 message type. 138 * 139 */ SetType(Type aType)140 void SetType(Type aType) { mType = aType; } 141 142 /** 143 * Returns the DHCPv6 message transaction identifier. 144 * 145 * @returns The DHCPv6 message transaction identifier. 146 * 147 */ GetTransactionId(void) const148 const TransactionId &GetTransactionId(void) const { return mTransactionId; } 149 150 /** 151 * Sets the DHCPv6 message transaction identifier. 152 * 153 * @param[in] aTransactionId The DHCPv6 message transaction identifier. 154 * 155 */ SetTransactionId(const TransactionId & aTransactionId)156 void SetTransactionId(const TransactionId &aTransactionId) { mTransactionId = aTransactionId; } 157 158 private: 159 Type mType; 160 TransactionId mTransactionId; 161 } OT_TOOL_PACKED_END; 162 163 /** 164 * DHCPv6 Option Codes. 165 * 166 */ 167 enum Code : uint16_t 168 { 169 kOptionClientIdentifier = 1, 170 kOptionServerIdentifier = 2, 171 kOptionIaNa = 3, 172 kOptionIaTa = 4, 173 kOptionIaAddress = 5, 174 kOptionRequestOption = 6, 175 kOptionPreference = 7, 176 kOptionElapsedTime = 8, 177 kOptionRelayMessage = 9, 178 kOptionAuthentication = 11, 179 kOptionServerUnicast = 12, 180 kOptionStatusCode = 13, 181 kOptionRapidCommit = 14, 182 kOptionUserClass = 15, 183 kOptionVendorClass = 16, 184 kOptionVendorSpecificInformation = 17, 185 kOptionInterfaceId = 18, 186 kOptionReconfigureMessage = 19, 187 kOptionReconfigureAccept = 20, 188 kOptionLeaseQuery = 44, 189 kOptionClientData = 45, 190 kOptionClientLastTransactionTime = 46, 191 }; 192 193 /** 194 * Implements DHCPv6 option. 195 * 196 */ 197 OT_TOOL_PACKED_BEGIN 198 class Option 199 { 200 public: 201 /** 202 * Initializes the DHCPv6 option to all zeros. 203 * 204 */ Init(void)205 void Init(void) 206 { 207 mCode = 0; 208 mLength = 0; 209 } 210 211 /** 212 * Returns the DHCPv6 option code. 213 * 214 * @returns The DHCPv6 option code. 215 * 216 */ GetCode(void) const217 Code GetCode(void) const { return static_cast<Code>(BigEndian::HostSwap16(mCode)); } 218 219 /** 220 * Sets the DHCPv6 option code. 221 * 222 * @param[in] aCode The DHCPv6 option code. 223 * 224 */ SetCode(Code aCode)225 void SetCode(Code aCode) { mCode = BigEndian::HostSwap16(static_cast<uint16_t>(aCode)); } 226 227 /** 228 * Returns the length of DHCPv6 option. 229 * 230 * @returns The length of DHCPv6 option. 231 * 232 */ GetLength(void) const233 uint16_t GetLength(void) const { return BigEndian::HostSwap16(mLength); } 234 235 /** 236 * Sets the length of DHCPv6 option. 237 * 238 * @param[in] aLength The length of DHCPv6 option. 239 * 240 */ SetLength(uint16_t aLength)241 void SetLength(uint16_t aLength) { mLength = BigEndian::HostSwap16(aLength); } 242 243 private: 244 uint16_t mCode; 245 uint16_t mLength; 246 } OT_TOOL_PACKED_END; 247 248 /** 249 * DHCP6 Unique Identifier (DUID) Type. 250 * 251 */ 252 enum DuidType : uint16_t 253 { 254 kDuidLinkLayerAddressPlusTime = 1, ///< Link-layer address plus time (DUID-LLT). 255 kDuidEnterpriseNumber = 2, ///< Vendor-assigned unique ID based on Enterprise Number (DUID-EN). 256 kDuidLinkLayerAddress = 3, ///< Link-layer address (DUID-LL). 257 }; 258 259 OT_TOOL_PACKED_BEGIN 260 class ClientIdentifier : public Option 261 { 262 public: 263 /** 264 * Initializes the DHCPv6 Option. 265 * 266 */ Init(void)267 void Init(void) 268 { 269 SetCode(kOptionClientIdentifier); 270 SetLength(sizeof(*this) - sizeof(Option)); 271 } 272 273 /** 274 * Returns the client DUID Type. 275 * 276 * @returns The client DUID Type. 277 * 278 */ GetDuidType(void) const279 DuidType GetDuidType(void) const { return static_cast<DuidType>(BigEndian::HostSwap16(mDuidType)); } 280 281 /** 282 * Sets the client DUID Type. 283 * 284 * @param[in] aDuidType The client DUID Type. 285 * 286 */ SetDuidType(DuidType aDuidType)287 void SetDuidType(DuidType aDuidType) { mDuidType = BigEndian::HostSwap16(static_cast<uint16_t>(aDuidType)); } 288 289 /** 290 * Returns the client Duid HardwareType. 291 * 292 * @returns The client Duid HardwareType. 293 * 294 */ GetDuidHardwareType(void) const295 uint16_t GetDuidHardwareType(void) const { return BigEndian::HostSwap16(mDuidHardwareType); } 296 297 /** 298 * Sets the client Duid HardwareType. 299 * 300 * @param[in] aDuidHardwareType The client Duid HardwareType. 301 * 302 */ SetDuidHardwareType(uint16_t aDuidHardwareType)303 void SetDuidHardwareType(uint16_t aDuidHardwareType) 304 { 305 mDuidHardwareType = BigEndian::HostSwap16(aDuidHardwareType); 306 } 307 308 /** 309 * Returns the client LinkLayerAddress. 310 * 311 * @returns The link-layer address. 312 * 313 */ GetDuidLinkLayerAddress(void) const314 const Mac::ExtAddress &GetDuidLinkLayerAddress(void) const { return mDuidLinkLayerAddress; } 315 316 /** 317 * Sets the client LinkLayerAddress. 318 * 319 * @param[in] aDuidLinkLayerAddress The client LinkLayerAddress. 320 * 321 */ SetDuidLinkLayerAddress(const Mac::ExtAddress & aDuidLinkLayerAddress)322 void SetDuidLinkLayerAddress(const Mac::ExtAddress &aDuidLinkLayerAddress) 323 { 324 mDuidLinkLayerAddress = aDuidLinkLayerAddress; 325 } 326 327 private: 328 uint16_t mDuidType; 329 uint16_t mDuidHardwareType; 330 Mac::ExtAddress mDuidLinkLayerAddress; 331 } OT_TOOL_PACKED_END; 332 333 OT_TOOL_PACKED_BEGIN 334 class ServerIdentifier : public Option 335 { 336 public: 337 /** 338 * Initializes the DHCPv6 Option. 339 * 340 */ Init(void)341 void Init(void) 342 { 343 SetCode(kOptionServerIdentifier); 344 SetLength(sizeof(*this) - sizeof(Option)); 345 } 346 347 /** 348 * Returns the server DUID Type. 349 * 350 * @returns The server DUID Type. 351 * 352 */ GetDuidType(void) const353 DuidType GetDuidType(void) const { return static_cast<DuidType>(BigEndian::HostSwap16(mDuidType)); } 354 355 /** 356 * Sets the server DUID Type. 357 * 358 * @param[in] aDuidType The server DUID Type. 359 * 360 */ SetDuidType(DuidType aDuidType)361 void SetDuidType(DuidType aDuidType) { mDuidType = BigEndian::HostSwap16(static_cast<uint16_t>(aDuidType)); } 362 363 /** 364 * Returns the server DUID HardwareType. 365 * 366 * @returns The server DUID HardwareType. 367 * 368 */ GetDuidHardwareType(void) const369 uint16_t GetDuidHardwareType(void) const { return BigEndian::HostSwap16(mDuidHardwareType); } 370 371 /** 372 * Sets the server DUID HardwareType. 373 * 374 * @param[in] aDuidHardwareType The server DUID HardwareType. 375 * 376 */ SetDuidHardwareType(uint16_t aDuidHardwareType)377 void SetDuidHardwareType(uint16_t aDuidHardwareType) 378 { 379 mDuidHardwareType = BigEndian::HostSwap16(aDuidHardwareType); 380 } 381 382 /** 383 * Returns the server LinkLayerAddress. 384 * 385 * @returns The link-layer address. 386 * 387 */ GetDuidLinkLayerAddress(void) const388 const Mac::ExtAddress &GetDuidLinkLayerAddress(void) const { return mDuidLinkLayerAddress; } 389 390 /** 391 * Sets the server LinkLayerAddress. 392 * 393 * @param[in] aDuidLinkLayerAddress The server LinkLayerAddress. 394 * 395 */ SetDuidLinkLayerAddress(const Mac::ExtAddress & aDuidLinkLayerAddress)396 void SetDuidLinkLayerAddress(const Mac::ExtAddress &aDuidLinkLayerAddress) 397 { 398 mDuidLinkLayerAddress = aDuidLinkLayerAddress; 399 } 400 401 private: 402 uint16_t mDuidType; 403 uint16_t mDuidHardwareType; 404 Mac::ExtAddress mDuidLinkLayerAddress; 405 } OT_TOOL_PACKED_END; 406 407 /** 408 * Represents an Identity Association for Non-temporary Address DHCPv6 option. 409 * 410 */ 411 OT_TOOL_PACKED_BEGIN 412 class IaNa : public Option 413 { 414 public: 415 static constexpr uint32_t kDefaultT1 = 0xffffffffU; ///< Default T1 value. 416 static constexpr uint32_t kDefaultT2 = 0xffffffffU; ///< Default T2 value. 417 418 /** 419 * Initializes the DHCPv6 Option. 420 * 421 */ Init(void)422 void Init(void) 423 { 424 SetCode(kOptionIaNa); 425 SetLength(sizeof(*this) - sizeof(Option)); 426 } 427 428 /** 429 * Returns client IAID. 430 * 431 * @returns The client IAID. 432 * 433 */ GetIaid(void) const434 uint32_t GetIaid(void) const { return BigEndian::HostSwap32(mIaid); } 435 436 /** 437 * Sets the client IAID. 438 * 439 * @param[in] aIaid The client IAID. 440 * 441 */ SetIaid(uint32_t aIaid)442 void SetIaid(uint32_t aIaid) { mIaid = BigEndian::HostSwap32(aIaid); } 443 444 /** 445 * Returns T1. 446 * 447 * @returns The value of T1. 448 * 449 */ GetT1(void) const450 uint32_t GetT1(void) const { return BigEndian::HostSwap32(mT1); } 451 452 /** 453 * Sets the value of T1. 454 * 455 * @param[in] aT1 The value of T1. 456 * 457 */ SetT1(uint32_t aT1)458 void SetT1(uint32_t aT1) { mT1 = BigEndian::HostSwap32(aT1); } 459 460 /** 461 * Returns T2. 462 * 463 * @returns The value of T2. 464 * 465 */ GetT2(void) const466 uint32_t GetT2(void) const { return BigEndian::HostSwap32(mT2); } 467 468 /** 469 * Sets the value of T2. 470 * 471 * @param[in] aT2 The value of T2. 472 * 473 */ SetT2(uint32_t aT2)474 void SetT2(uint32_t aT2) { mT2 = BigEndian::HostSwap32(aT2); } 475 476 private: 477 uint32_t mIaid; 478 uint32_t mT1; 479 uint32_t mT2; 480 } OT_TOOL_PACKED_END; 481 482 /** 483 * Represents an Identity Association Address DHCPv6 option. 484 * 485 */ 486 OT_TOOL_PACKED_BEGIN 487 class IaAddress : public Option 488 { 489 public: 490 static constexpr uint32_t kDefaultPreferredLifetime = 0xffffffffU; ///< Default preferred lifetime. 491 static constexpr uint32_t kDefaultValidLifetime = 0xffffffffU; ///< Default valid lifetime. 492 493 /** 494 * Initializes the DHCPv6 Option. 495 * 496 */ Init(void)497 void Init(void) 498 { 499 SetCode(kOptionIaAddress); 500 SetLength(sizeof(*this) - sizeof(Option)); 501 } 502 503 /** 504 * Returns a reference to the IPv6 address. 505 * 506 * @returns A reference to the IPv6 address. 507 * 508 */ GetAddress(void)509 Ip6::Address &GetAddress(void) { return mAddress; } 510 511 /** 512 * Returns a reference to the IPv6 address. 513 * 514 * @returns A reference to the IPv6 address. 515 * 516 */ GetAddress(void) const517 const Ip6::Address &GetAddress(void) const { return mAddress; } 518 519 /** 520 * Sets the IPv6 address. 521 * 522 * @param[in] aAddress The reference to the IPv6 address to set. 523 * 524 */ SetAddress(const Ip6::Address & aAddress)525 void SetAddress(const Ip6::Address &aAddress) { mAddress = aAddress; } 526 527 /** 528 * Returns the preferred lifetime of the IPv6 address. 529 * 530 * @returns The preferred lifetime of the IPv6 address. 531 * 532 */ GetPreferredLifetime(void) const533 uint32_t GetPreferredLifetime(void) const { return BigEndian::HostSwap32(mPreferredLifetime); } 534 535 /** 536 * Sets the preferred lifetime of the IPv6 address. 537 * 538 * @param[in] aPreferredLifetime The preferred lifetime of the IPv6 address. 539 * 540 */ SetPreferredLifetime(uint32_t aPreferredLifetime)541 void SetPreferredLifetime(uint32_t aPreferredLifetime) 542 { 543 mPreferredLifetime = BigEndian::HostSwap32(aPreferredLifetime); 544 } 545 546 /** 547 * Returns the valid lifetime of the IPv6 address. 548 * 549 * @returns The valid lifetime of the IPv6 address. 550 * 551 */ GetValidLifetime(void) const552 uint32_t GetValidLifetime(void) const { return BigEndian::HostSwap32(mValidLifetime); } 553 554 /** 555 * Sets the valid lifetime of the IPv6 address. 556 * 557 * @param[in] aValidLifetime The valid lifetime of the IPv6 address. 558 * 559 */ SetValidLifetime(uint32_t aValidLifetime)560 void SetValidLifetime(uint32_t aValidLifetime) { mValidLifetime = BigEndian::HostSwap32(aValidLifetime); } 561 562 private: 563 Ip6::Address mAddress; 564 uint32_t mPreferredLifetime; 565 uint32_t mValidLifetime; 566 } OT_TOOL_PACKED_END; 567 568 /** 569 * Represents an Elapsed Time DHCPv6 option. 570 * 571 */ 572 OT_TOOL_PACKED_BEGIN 573 class ElapsedTime : public Option 574 { 575 public: 576 /** 577 * Initializes the DHCPv6 Option. 578 * 579 */ Init(void)580 void Init(void) 581 { 582 SetCode(kOptionElapsedTime); 583 SetLength(sizeof(*this) - sizeof(Option)); 584 } 585 586 /** 587 * Returns the elapsed time since solicit starts. 588 * 589 * @returns The elapsed time since solicit starts. 590 * 591 */ GetElapsedTime(void) const592 uint16_t GetElapsedTime(void) const { return BigEndian::HostSwap16(mElapsedTime); } 593 594 /** 595 * Sets the elapsed time since solicit starts. 596 * 597 * @param[in] aElapsedTime The elapsed time since solicit starts. 598 * 599 */ SetElapsedTime(uint16_t aElapsedTime)600 void SetElapsedTime(uint16_t aElapsedTime) { mElapsedTime = BigEndian::HostSwap16(aElapsedTime); } 601 602 private: 603 uint16_t mElapsedTime; 604 } OT_TOOL_PACKED_END; 605 606 /** 607 * Status Code. 608 * 609 */ 610 enum Status : uint16_t 611 { 612 kStatusSuccess = 0, 613 kStatusUnspecFail = 1, 614 kStatusNoAddrsAvail = 2, 615 kStatusNoBinding = 3, 616 kStatusNotOnLink = 4, 617 kStatusUseMulticast = 5, 618 kUnknownQueryType = 7, 619 kMalformedQuery = 8, 620 kNotConfigured = 9, 621 kNotAllowed = 10, 622 }; 623 624 /** 625 * Represents an Status Code DHCPv6 option. 626 * 627 */ 628 OT_TOOL_PACKED_BEGIN 629 class StatusCode : public Option 630 { 631 public: 632 /** 633 * Initializes the DHCPv6 Option. 634 * 635 */ Init(void)636 void Init(void) 637 { 638 SetCode(kOptionStatusCode); 639 SetLength(sizeof(*this) - sizeof(Option)); 640 } 641 642 /** 643 * Returns the status code. 644 * 645 * @returns The status code. 646 * 647 */ GetStatusCode(void) const648 Status GetStatusCode(void) const { return static_cast<Status>(BigEndian::HostSwap16(mStatus)); } 649 650 /** 651 * Sets the status code. 652 * 653 * @param[in] aStatus The status code. 654 * 655 */ SetStatusCode(Status aStatus)656 void SetStatusCode(Status aStatus) { mStatus = BigEndian::HostSwap16(static_cast<uint16_t>(aStatus)); } 657 658 private: 659 uint16_t mStatus; 660 } OT_TOOL_PACKED_END; 661 662 /** 663 * Represents an Rapid Commit DHCPv6 option. 664 * 665 */ 666 OT_TOOL_PACKED_BEGIN 667 class RapidCommit : public Option 668 { 669 public: 670 /** 671 * Initializes the DHCPv6 Option. 672 * 673 */ Init(void)674 void Init(void) 675 { 676 SetCode(kOptionRapidCommit); 677 SetLength(sizeof(*this) - sizeof(Option)); 678 } 679 } OT_TOOL_PACKED_END; 680 681 } // namespace Dhcp6 682 } // namespace ot 683 684 #endif // #if OPENTHREAD_CONFIG_DHCP6_SERVER_ENABLE || OPENTHREAD_CONFIG_DHCP6_CLIENT_ENABLE 685 686 #endif // DHCP6_HPP_ 687