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