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