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 IPv6 packet processing. 32 */ 33 34 #ifndef IP6_HEADERS_HPP_ 35 #define IP6_HEADERS_HPP_ 36 37 #include "openthread-core-config.h" 38 39 #include <stddef.h> 40 41 #include "common/clearable.hpp" 42 #include "common/encoding.hpp" 43 #include "common/message.hpp" 44 #include "net/ip6_address.hpp" 45 #include "net/ip6_types.hpp" 46 #include "net/netif.hpp" 47 #include "net/socket.hpp" 48 49 namespace ot { 50 51 /** 52 * @namespace ot::Ip6 53 * 54 * @brief 55 * This namespace includes definitions for IPv6 networking. 56 * 57 */ 58 namespace Ip6 { 59 60 /** 61 * @addtogroup core-ipv6 62 * 63 * @brief 64 * This module includes definitions for the IPv6 network layer. 65 * 66 * @{ 67 * 68 * @defgroup core-ip6-icmp6 ICMPv6 69 * @defgroup core-ip6-ip6 IPv6 70 * @defgroup core-ip6-mpl MPL 71 * @defgroup core-ip6-netif Network Interfaces 72 * 73 * @} 74 * 75 */ 76 77 /** 78 * @addtogroup core-ip6-ip6 79 * 80 * @brief 81 * This module includes definitions for core IPv6 networking. 82 * 83 * @{ 84 * 85 */ 86 87 /** 88 * Implements IPv6 header generation and parsing. 89 * 90 */ 91 OT_TOOL_PACKED_BEGIN 92 class Header : public Clearable<Header> 93 { 94 public: 95 static constexpr uint8_t kPayloadLengthFieldOffset = 4; ///< Offset of Payload Length field in IPv6 header. 96 static constexpr uint8_t kNextHeaderFieldOffset = 6; ///< Offset of Next Header field in IPv6 header. 97 static constexpr uint8_t kHopLimitFieldOffset = 7; ///< Offset of Hop Limit field in IPv6 header. 98 static constexpr uint8_t kSourceFieldOffset = 8; ///< Offset of Source Address field in IPv6 header. 99 static constexpr uint8_t kDestinationFieldOffset = 24; ///< Offset of Destination Address field in IPv6 header. 100 101 /** 102 * Initializes the Version to 6 and sets Traffic Class and Flow fields to zero. 103 * 104 * The other fields in the IPv6 header remain unchanged. 105 * 106 */ InitVersionTrafficClassFlow(void)107 void InitVersionTrafficClassFlow(void) { SetVerionTrafficClassFlow(kVersTcFlowInit); } 108 109 /** 110 * Indicates whether or not the header appears to be well-formed. 111 * 112 * @retval TRUE If the header appears to be well-formed. 113 * @retval FALSE If the header does not appear to be well-formed. 114 * 115 */ 116 bool IsValid(void) const; 117 118 /** 119 * Indicates whether or not the IPv6 Version is set to 6. 120 * 121 * @retval TRUE If the IPv6 Version is set to 6. 122 * @retval FALSE If the IPv6 Version is not set to 6. 123 * 124 */ IsVersion6(void) const125 bool IsVersion6(void) const { return (mVerTcFlow.m8[0] & kVersionMask) == kVersion6; } 126 127 /** 128 * Gets the combination of Version, Traffic Class, and Flow fields as a 32-bit value. 129 * 130 * @returns The Version, Traffic Class, and Flow fields as a 32-bit value. 131 * 132 */ GetVerionTrafficClassFlow(void) const133 uint32_t GetVerionTrafficClassFlow(void) const { return BigEndian::HostSwap32(mVerTcFlow.m32); } 134 135 /** 136 * Sets the combination of Version, Traffic Class, and Flow fields as a 32-bit value. 137 * 138 * @param[in] aVerTcFlow The Version, Traffic Class, and Flow fields as a 32-bit value. 139 * 140 */ SetVerionTrafficClassFlow(uint32_t aVerTcFlow)141 void SetVerionTrafficClassFlow(uint32_t aVerTcFlow) { mVerTcFlow.m32 = BigEndian::HostSwap32(aVerTcFlow); } 142 143 /** 144 * Gets the Traffic Class field. 145 * 146 * @returns The Traffic Class field. 147 * 148 */ GetTrafficClass(void) const149 uint8_t GetTrafficClass(void) const 150 { 151 return static_cast<uint8_t>((BigEndian::HostSwap16(mVerTcFlow.m16[0]) & kTrafficClassMask) >> 152 kTrafficClassOffset); 153 } 154 155 /** 156 * Sets the Traffic Class filed. 157 * 158 * @param[in] aTc The Traffic Class value. 159 * 160 */ SetTrafficClass(uint8_t aTc)161 void SetTrafficClass(uint8_t aTc) 162 { 163 mVerTcFlow.m16[0] = 164 BigEndian::HostSwap16((BigEndian::HostSwap16(mVerTcFlow.m16[0]) & ~kTrafficClassMask) | 165 ((static_cast<uint16_t>(aTc) << kTrafficClassOffset) & kTrafficClassMask)); 166 } 167 168 /** 169 * Gets the 6-bit Differentiated Services Code Point (DSCP) from Traffic Class field. 170 * 171 * @returns The DSCP value. 172 * 173 */ GetDscp(void) const174 uint8_t GetDscp(void) const 175 { 176 return static_cast<uint8_t>((BigEndian::HostSwap16(mVerTcFlow.m16[0]) & kDscpMask) >> kDscpOffset); 177 } 178 179 /** 180 * Sets 6-bit Differentiated Services Code Point (DSCP) in IPv6 header. 181 * 182 * @param[in] aDscp The DSCP value. 183 * 184 */ SetDscp(uint8_t aDscp)185 void SetDscp(uint8_t aDscp) 186 { 187 mVerTcFlow.m16[0] = BigEndian::HostSwap16((BigEndian::HostSwap16(mVerTcFlow.m16[0]) & ~kDscpMask) | 188 ((static_cast<uint16_t>(aDscp) << kDscpOffset) & kDscpMask)); 189 } 190 191 /** 192 * Gets the 2-bit Explicit Congestion Notification (ECN) from Traffic Class field. 193 * 194 * @returns The ECN value. 195 * 196 */ GetEcn(void) const197 Ecn GetEcn(void) const { return static_cast<Ecn>((mVerTcFlow.m8[1] & kEcnMask) >> kEcnOffset); } 198 199 /** 200 * Sets the 2-bit Explicit Congestion Notification (ECN) in IPv6 header.. 201 * 202 * @param[in] aEcn The ECN value. 203 * 204 */ SetEcn(Ecn aEcn)205 void SetEcn(Ecn aEcn) { mVerTcFlow.m8[1] = (mVerTcFlow.m8[1] & ~kEcnMask) | ((aEcn << kEcnOffset) & kEcnMask); } 206 207 /** 208 * Gets the 20-bit Flow field. 209 * 210 * @returns The Flow value. 211 * 212 */ GetFlow(void) const213 uint32_t GetFlow(void) const { return BigEndian::HostSwap32(mVerTcFlow.m32) & kFlowMask; } 214 215 /** 216 * Sets the 20-bit Flow field in IPv6 header. 217 * 218 * @param[in] aFlow The Flow value. 219 * 220 */ SetFlow(uint32_t aFlow)221 void SetFlow(uint32_t aFlow) 222 { 223 mVerTcFlow.m32 = 224 BigEndian::HostSwap32((BigEndian::HostSwap32(mVerTcFlow.m32) & ~kFlowMask) | (aFlow & kFlowMask)); 225 } 226 227 /** 228 * Returns the IPv6 Payload Length value. 229 * 230 * @returns The IPv6 Payload Length value. 231 * 232 */ GetPayloadLength(void) const233 uint16_t GetPayloadLength(void) const { return BigEndian::HostSwap16(mPayloadLength); } 234 235 /** 236 * Sets the IPv6 Payload Length value. 237 * 238 * @param[in] aLength The IPv6 Payload Length value. 239 * 240 */ SetPayloadLength(uint16_t aLength)241 void SetPayloadLength(uint16_t aLength) { mPayloadLength = BigEndian::HostSwap16(aLength); } 242 243 /** 244 * Returns the IPv6 Next Header value. 245 * 246 * @returns The IPv6 Next Header value. 247 * 248 */ GetNextHeader(void) const249 uint8_t GetNextHeader(void) const { return mNextHeader; } 250 251 /** 252 * Sets the IPv6 Next Header value. 253 * 254 * @param[in] aNextHeader The IPv6 Next Header value. 255 * 256 */ SetNextHeader(uint8_t aNextHeader)257 void SetNextHeader(uint8_t aNextHeader) { mNextHeader = aNextHeader; } 258 259 /** 260 * Returns the IPv6 Hop Limit value. 261 * 262 * @returns The IPv6 Hop Limit value. 263 * 264 */ GetHopLimit(void) const265 uint8_t GetHopLimit(void) const { return mHopLimit; } 266 267 /** 268 * Sets the IPv6 Hop Limit value. 269 * 270 * @param[in] aHopLimit The IPv6 Hop Limit value. 271 * 272 */ SetHopLimit(uint8_t aHopLimit)273 void SetHopLimit(uint8_t aHopLimit) { mHopLimit = aHopLimit; } 274 275 /** 276 * Returns the IPv6 Source address. 277 * 278 * @returns A reference to the IPv6 Source address. 279 * 280 */ GetSource(void)281 Address &GetSource(void) { return mSource; } 282 283 /** 284 * Returns the IPv6 Source address. 285 * 286 * @returns A reference to the IPv6 Source address. 287 * 288 */ GetSource(void) const289 const Address &GetSource(void) const { return mSource; } 290 291 /** 292 * Sets the IPv6 Source address. 293 * 294 * @param[in] aSource A reference to the IPv6 Source address. 295 * 296 */ SetSource(const Address & aSource)297 void SetSource(const Address &aSource) { mSource = aSource; } 298 299 /** 300 * Returns the IPv6 Destination address. 301 * 302 * @returns A reference to the IPv6 Destination address. 303 * 304 */ GetDestination(void)305 Address &GetDestination(void) { return mDestination; } 306 307 /** 308 * Returns the IPv6 Destination address. 309 * 310 * @returns A reference to the IPv6 Destination address. 311 * 312 */ GetDestination(void) const313 const Address &GetDestination(void) const { return mDestination; } 314 315 /** 316 * Sets the IPv6 Destination address. 317 * 318 * @param[in] aDestination A reference to the IPv6 Destination address. 319 * 320 */ SetDestination(const Address & aDestination)321 void SetDestination(const Address &aDestination) { mDestination = aDestination; } 322 323 /** 324 * Parses and validates the IPv6 header from a given message. 325 * 326 * The header is read from @p aMessage at offset zero. 327 * 328 * @param[in] aMessage The IPv6 message. 329 * 330 * @retval kErrorNone Successfully parsed the IPv6 header from @p aMessage. 331 * @retval kErrorParse Malformed IPv6 header or message (e.g., message does not contained expected payload length). 332 * 333 */ 334 Error ParseFrom(const Message &aMessage); 335 336 private: 337 // IPv6 header `mVerTcFlow` field: 338 // 339 // | m16[0] | m16[1] | 340 // | m8[0] | m8[1] | m8[2] | m8[3] | 341 // +---------------+---------------+---------------+---------------+ 342 // |7 6 5 4 3 2 1 0|7 6 5 4 3 2 1 0|7 6 5 4 3 2 1 0|7 6 5 4 3 2 1 0| 343 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 344 // |Version| DSCP |ECN| Flow Label | 345 // | | Traffic Class | | 346 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 347 348 static constexpr uint8_t kVersion6 = 0x60; // Use with `mVerTcFlow.m8[0]` 349 static constexpr uint8_t kVersionMask = 0xf0; // Use with `mVerTcFlow.m8[0]` 350 static constexpr uint8_t kTrafficClassOffset = 4; // Use with `mVerTcFlow.m16[0]` 351 static constexpr uint16_t kTrafficClassMask = 0x0ff0; // Use with `mVerTcFlow.m16[0]` 352 static constexpr uint8_t kDscpOffset = 6; // Use with `mVerTcFlow.m16[0]` 353 static constexpr uint16_t kDscpMask = 0x0fc0; // Use with `mVerTcFlow.m16[0]` 354 static constexpr uint8_t kEcnOffset = 4; // Use with `mVerTcFlow.m8[1]` 355 static constexpr uint8_t kEcnMask = 0x30; // Use with `mVerTcFlow.m8[1]` 356 static constexpr uint32_t kFlowMask = 0x000fffff; // Use with `mVerTcFlow.m32` 357 static constexpr uint32_t kVersTcFlowInit = 0x60000000; // Version 6, TC and flow zero. 358 359 union OT_TOOL_PACKED_FIELD 360 { 361 uint8_t m8[sizeof(uint32_t) / sizeof(uint8_t)]; 362 uint16_t m16[sizeof(uint32_t) / sizeof(uint16_t)]; 363 uint32_t m32; 364 } mVerTcFlow; 365 uint16_t mPayloadLength; 366 uint8_t mNextHeader; 367 uint8_t mHopLimit; 368 Address mSource; 369 Address mDestination; 370 } OT_TOOL_PACKED_END; 371 372 /** 373 * Implements IPv6 Extension Header generation and processing. 374 * 375 */ 376 OT_TOOL_PACKED_BEGIN 377 class ExtensionHeader 378 { 379 public: 380 /** 381 * This constant defines the size of Length unit in bytes. 382 * 383 * The Length field is in 8-bytes unit. The total size of `ExtensionHeader` MUST be a multiple of 8. 384 * 385 */ 386 static constexpr uint16_t kLengthUnitSize = 8; 387 388 /** 389 * Returns the IPv6 Next Header value. 390 * 391 * @returns The IPv6 Next Header value. 392 * 393 */ GetNextHeader(void) const394 uint8_t GetNextHeader(void) const { return mNextHeader; } 395 396 /** 397 * Sets the IPv6 Next Header value. 398 * 399 * @param[in] aNextHeader The IPv6 Next Header value. 400 * 401 */ SetNextHeader(uint8_t aNextHeader)402 void SetNextHeader(uint8_t aNextHeader) { mNextHeader = aNextHeader; } 403 404 /** 405 * Returns the IPv6 Header Extension Length value. 406 * 407 * The Length is in 8-byte units and does not include the first 8 bytes. 408 * 409 * @returns The IPv6 Header Extension Length value. 410 * 411 */ GetLength(void) const412 uint8_t GetLength(void) const { return mLength; } 413 414 /** 415 * Sets the IPv6 Header Extension Length value. 416 * 417 * The Length is in 8-byte units and does not include the first 8 bytes. 418 * 419 * @param[in] aLength The IPv6 Header Extension Length value. 420 * 421 */ SetLength(uint8_t aLength)422 void SetLength(uint8_t aLength) { mLength = aLength; } 423 424 /** 425 * Returns the size (number of bytes) of the Extension Header including Next Header and Length fields. 426 * 427 * @returns The size (number of bytes) of the Extension Header. 428 * 429 */ GetSize(void) const430 uint16_t GetSize(void) const { return kLengthUnitSize * (mLength + 1); } 431 432 private: 433 // | m8[0] | m8[1] | m8[2] | m8[3] | 434 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 435 // | Next Header | Header Length | . . . | 436 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 437 438 uint8_t mNextHeader; 439 uint8_t mLength; 440 } OT_TOOL_PACKED_END; 441 442 /** 443 * Implements IPv6 Hop-by-Hop Options Header generation and parsing. 444 * 445 */ 446 OT_TOOL_PACKED_BEGIN 447 class HopByHopHeader : public ExtensionHeader 448 { 449 } OT_TOOL_PACKED_END; 450 451 /** 452 * Implements IPv6 Options generation and parsing. 453 * 454 */ 455 OT_TOOL_PACKED_BEGIN 456 class Option 457 { 458 public: 459 /** 460 * IPv6 Option Type actions for unrecognized IPv6 Options. 461 * 462 */ 463 enum Action : uint8_t 464 { 465 kActionSkip = 0x00, ///< Skip over this option and continue processing the header. 466 kActionDiscard = 0x40, ///< Discard the packet. 467 kActionForceIcmp = 0x80, ///< Discard the packet and forcibly send an ICMP Parameter Problem. 468 kActionIcmp = 0xc0, ///< Discard packet and conditionally send an ICMP Parameter Problem. 469 }; 470 471 /** 472 * Returns the IPv6 Option Type value. 473 * 474 * @returns The IPv6 Option Type value. 475 * 476 */ GetType(void) const477 uint8_t GetType(void) const { return mType; } 478 479 /** 480 * Indicates whether IPv6 Option is padding (either Pad1 or PadN). 481 * 482 * @retval TRUE The Option is padding. 483 * @retval FALSE The Option is not padding. 484 * 485 */ IsPadding(void) const486 bool IsPadding(void) const { return (mType == kTypePad1) || (mType == kTypePadN); } 487 488 /** 489 * Returns the IPv6 Option action for unrecognized IPv6 Options. 490 * 491 * @returns The IPv6 Option action for unrecognized IPv6 Options. 492 * 493 */ GetAction(void) const494 Action GetAction(void) const { return static_cast<Action>(mType & kActionMask); } 495 496 /** 497 * Returns the IPv6 Option Length value. 498 * 499 * @returns The IPv6 Option Length value. 500 * 501 */ GetLength(void) const502 uint8_t GetLength(void) const { return mLength; } 503 504 /** 505 * Returns the size (number of bytes) of the IPv6 Option. 506 * 507 * Returns the proper size of the Option independent of its type, particularly if Option is Pad1 (which 508 * does not follow the common Option header structure and has only Type field with no Length field). For other 509 * Option types, the returned size includes the Type and Length fields. 510 * 511 * @returns The size of the Option. 512 * 513 */ 514 uint16_t GetSize(void) const; 515 516 /** 517 * Parses and validates the IPv6 Option from a given message. 518 * 519 * The Option is read from @p aOffset in @p aMessage. This method then checks that the entire Option is present 520 * in @p aMessage before the @p aEndOffset. 521 * 522 * @param[in] aMessage The IPv6 message. 523 * @param[in] aOffset The offset in @p aMessage to read the IPv6 Option. 524 * @param[in] aEndOffset The end offset in @p aMessage. 525 * 526 * @retval kErrorNone Successfully parsed the IPv6 option from @p aMessage. 527 * @retval kErrorParse Malformed IPv6 Option or Option is not contained within @p aMessage by @p aEndOffset. 528 * 529 */ 530 Error ParseFrom(const Message &aMessage, uint16_t aOffset, uint16_t aEndOffset); 531 532 protected: 533 static constexpr uint8_t kTypePad1 = 0x00; ///< Pad1 Option Type. 534 static constexpr uint8_t kTypePadN = 0x01; ///< PanN Option Type. 535 536 /** 537 * Sets the IPv6 Option Type value. 538 * 539 * @param[in] aType The IPv6 Option Type value. 540 * 541 */ SetType(uint8_t aType)542 void SetType(uint8_t aType) { mType = aType; } 543 544 /** 545 * Sets the IPv6 Option Length value. 546 * 547 * @param[in] aLength The IPv6 Option Length value. 548 * 549 */ SetLength(uint8_t aLength)550 void SetLength(uint8_t aLength) { mLength = aLength; } 551 552 private: 553 static constexpr uint8_t kActionMask = 0xc0; 554 555 uint8_t mType; 556 uint8_t mLength; 557 } OT_TOOL_PACKED_END; 558 559 /** 560 * Implements IPv6 Pad Options (Pad1 or PadN) generation. 561 * 562 */ 563 OT_TOOL_PACKED_BEGIN 564 class PadOption : public Option, private Clearable<PadOption> 565 { 566 friend class Clearable<PadOption>; 567 568 public: 569 /** 570 * Initializes the Pad Option for a given total Pad size. 571 * 572 * The @p aPadSize MUST be from range 1-7. Otherwise the behavior of this method is undefined. 573 * 574 * @param[in] aPadSize The total number of needed padding bytes. 575 * 576 */ 577 void InitForPadSize(uint8_t aPadSize); 578 579 /** 580 * Initializes the Pad Option for padding an IPv6 Extension header with a given current size. 581 * 582 * The Extension Header Length is in 8-bytes unit, so the total size should be a multiple of 8. This method 583 * determines the Pad Option size needed for appending to Extension Header based on it current size @p aHeaderSize 584 * so to make it a multiple of 8. This method returns `kErrorAlready` when the @p aHeaderSize is already 585 * a multiple of 8 (i.e., no padding is needed). 586 * 587 * @param[in] aHeaderSize The current IPv6 Extension header size (in bytes). 588 * 589 * @retval kErrorNone The Pad Option is successfully initialized. 590 * @retval kErrorAlready The @p aHeaderSize is already a multiple of 8 and no padding is needed. 591 * 592 */ 593 Error InitToPadHeaderWithSize(uint16_t aHeaderSize); 594 595 private: 596 static constexpr uint8_t kMaxLength = 5; 597 598 uint8_t mPads[kMaxLength]; 599 } OT_TOOL_PACKED_END; 600 601 /** 602 * Implements IPv6 Fragment Header generation and parsing. 603 * 604 */ 605 OT_TOOL_PACKED_BEGIN 606 class FragmentHeader 607 { 608 public: 609 /** 610 * Initializes the IPv6 Fragment header. 611 * 612 */ Init(void)613 void Init(void) 614 { 615 mReserved = 0; 616 mOffsetMore = 0; 617 mIdentification = 0; 618 } 619 620 /** 621 * Returns the IPv6 Next Header value. 622 * 623 * @returns The IPv6 Next Header value. 624 * 625 */ GetNextHeader(void) const626 uint8_t GetNextHeader(void) const { return mNextHeader; } 627 628 /** 629 * Sets the IPv6 Next Header value. 630 * 631 * @param[in] aNextHeader The IPv6 Next Header value. 632 * 633 */ SetNextHeader(uint8_t aNextHeader)634 void SetNextHeader(uint8_t aNextHeader) { mNextHeader = aNextHeader; } 635 636 /** 637 * Returns the Fragment Offset value. 638 * 639 * @returns The Fragment Offset value. 640 * 641 */ GetOffset(void) const642 uint16_t GetOffset(void) const { return (BigEndian::HostSwap16(mOffsetMore) & kOffsetMask) >> kOffsetOffset; } 643 644 /** 645 * Sets the Fragment Offset value. 646 * 647 * @param[in] aOffset The Fragment Offset value. 648 */ SetOffset(uint16_t aOffset)649 void SetOffset(uint16_t aOffset) 650 { 651 uint16_t tmp = BigEndian::HostSwap16(mOffsetMore); 652 tmp = (tmp & ~kOffsetMask) | ((aOffset << kOffsetOffset) & kOffsetMask); 653 mOffsetMore = BigEndian::HostSwap16(tmp); 654 } 655 656 /** 657 * Returns the M flag value. 658 * 659 * @returns The M flag value. 660 * 661 */ IsMoreFlagSet(void) const662 bool IsMoreFlagSet(void) const { return BigEndian::HostSwap16(mOffsetMore) & kMoreFlag; } 663 664 /** 665 * Clears the M flag value. 666 * 667 */ ClearMoreFlag(void)668 void ClearMoreFlag(void) { mOffsetMore = BigEndian::HostSwap16(BigEndian::HostSwap16(mOffsetMore) & ~kMoreFlag); } 669 670 /** 671 * Sets the M flag value. 672 * 673 */ SetMoreFlag(void)674 void SetMoreFlag(void) { mOffsetMore = BigEndian::HostSwap16(BigEndian::HostSwap16(mOffsetMore) | kMoreFlag); } 675 676 /** 677 * Returns the frame identification. 678 * 679 * @returns The frame identification. 680 * 681 */ GetIdentification(void) const682 uint32_t GetIdentification(void) const { return mIdentification; } 683 684 /** 685 * Sets the frame identification. 686 * 687 * @param[in] aIdentification The fragment identification value. 688 */ SetIdentification(uint32_t aIdentification)689 void SetIdentification(uint32_t aIdentification) { mIdentification = aIdentification; } 690 691 /** 692 * Returns the next valid payload length for a fragment. 693 * 694 * @param[in] aLength The payload length to be validated for a fragment. 695 * 696 * @returns Valid IPv6 fragment payload length. 697 * 698 */ MakeDivisibleByEight(uint16_t aLength)699 static inline uint16_t MakeDivisibleByEight(uint16_t aLength) { return aLength & 0xfff8; } 700 701 /** 702 * Converts the fragment offset of 8-octet units into bytes. 703 * 704 * @param[in] aOffset The fragment offset in 8-octet units. 705 * 706 * @returns The fragment offset in bytes. 707 * 708 */ FragmentOffsetToBytes(uint16_t aOffset)709 static inline uint16_t FragmentOffsetToBytes(uint16_t aOffset) { return static_cast<uint16_t>(aOffset << 3); } 710 711 /** 712 * Converts a fragment offset in bytes into a fragment offset in 8-octet units. 713 * 714 * @param[in] aOffset The fragment offset in bytes. 715 * 716 * @returns The fragment offset in 8-octet units. 717 */ BytesToFragmentOffset(uint16_t aOffset)718 static inline uint16_t BytesToFragmentOffset(uint16_t aOffset) { return aOffset >> 3; } 719 720 private: 721 static constexpr uint8_t kOffsetOffset = 3; 722 static constexpr uint16_t kOffsetMask = 0xfff8; 723 static constexpr uint16_t kMoreFlag = 1; 724 725 uint8_t mNextHeader; 726 uint8_t mReserved; 727 uint16_t mOffsetMore; 728 uint32_t mIdentification; 729 } OT_TOOL_PACKED_END; 730 731 /** 732 * @} 733 * 734 */ 735 736 } // namespace Ip6 737 } // namespace ot 738 739 #endif // IP6_HEADERS_HPP_ 740