1 /* 2 * Copyright (c) 2020, 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 Neighbor Discovery (ND). 32 * 33 * See RFC 4861 (https://tools.ietf.org/html/rfc4861) and RFC 4191 (https://tools.ietf.org/html/rfc4191). 34 * 35 */ 36 37 #ifndef ND6_HPP_ 38 #define ND6_HPP_ 39 40 #include "openthread-core-config.h" 41 42 #include <stdint.h> 43 44 #include <openthread/netdata.h> 45 #include <openthread/platform/toolchain.h> 46 47 #include "common/const_cast.hpp" 48 #include "common/encoding.hpp" 49 #include "common/equatable.hpp" 50 #include "net/icmp6.hpp" 51 #include "net/ip6.hpp" 52 #include "thread/network_data_types.hpp" 53 54 using ot::Encoding::BigEndian::HostSwap16; 55 using ot::Encoding::BigEndian::HostSwap32; 56 57 namespace ot { 58 namespace Ip6 { 59 namespace Nd { 60 61 typedef NetworkData::RoutePreference RoutePreference; ///< Route Preference 62 63 /** 64 * This class represents the variable length options in Neighbor Discovery messages. 65 * 66 * @sa PrefixInfoOption 67 * @sa RouteInfoOption 68 * 69 */ 70 OT_TOOL_PACKED_BEGIN 71 class Option 72 { 73 friend class RouterAdvertMessage; 74 75 public: 76 enum Type : uint8_t 77 { 78 kTypePrefixInfo = 3, ///< Prefix Information Option. 79 kTypeRouteInfo = 24, ///< Route Information Option. 80 }; 81 82 static constexpr uint16_t kLengthUnit = 8; ///< The unit of length in octets. 83 84 /** 85 * This method gets the option type. 86 * 87 * @returns The option type. 88 * 89 */ GetType(void) const90 uint8_t GetType(void) const { return mType; } 91 92 /** 93 * This method sets the option type. 94 * 95 * @param[in] aType The option type. 96 * 97 * 98 */ SetType(Type aType)99 void SetType(Type aType) { mType = aType; } 100 101 /** 102 * This method sets the length based on a given total option size in bytes. 103 * 104 * Th option must end on a 64-bit boundary, so the length is derived as `(aSize + 7) / 8 * 8`. 105 * 106 * @param[in] aSize The size of option in bytes. 107 * 108 */ SetSize(uint16_t aSize)109 void SetSize(uint16_t aSize) { mLength = static_cast<uint8_t>((aSize + kLengthUnit - 1) / kLengthUnit); } 110 111 /** 112 * This method returns the size of the option in bytes. 113 * 114 * @returns The size of the option in bytes. 115 * 116 */ GetSize(void) const117 uint16_t GetSize(void) const { return mLength * kLengthUnit; } 118 119 /** 120 * This method sets the length of the option (in unit of 8 bytes). 121 * 122 * @param[in] aLength The length of the option in unit of 8 bytes. 123 * 124 */ SetLength(uint8_t aLength)125 void SetLength(uint8_t aLength) { mLength = aLength; } 126 127 /** 128 * This method returns the length of the option (in unit of 8 bytes). 129 * 130 * @returns The length of the option in unit of 8 bytes. 131 * 132 */ GetLength(void) const133 uint16_t GetLength(void) const { return mLength; } 134 135 /** 136 * This method indicates whether or not this option is valid. 137 * 138 * @retval TRUE The option is valid. 139 * @retval FALSE The option is not valid. 140 * 141 */ IsValid(void) const142 bool IsValid(void) const { return mLength > 0; } 143 144 private: 145 class Iterator : public Unequatable<Iterator> 146 { 147 public: 148 Iterator(void); 149 Iterator(const void *aStart, const void *aEnd); 150 operator *(void)151 const Option &operator*(void) { return *mOption; } operator ++(void)152 void operator++(void) { Advance(); } operator ++(int)153 void operator++(int) { Advance(); } operator ==(const Iterator & aOther) const154 bool operator==(const Iterator &aOther) const { return mOption == aOther.mOption; } 155 156 private: 157 static const Option *Next(const Option *aOption); 158 void Advance(void); 159 const Option *Validate(const Option *aOption) const; 160 161 const Option *mOption; 162 const Option *mEnd; 163 }; 164 165 uint8_t mType; // Type of the option. 166 uint8_t mLength; // Length of the option in unit of 8 octets, including the `mType` and `mLength` fields. 167 } OT_TOOL_PACKED_END; 168 169 /** 170 * This class represents the Prefix Information Option. 171 * 172 * See section 4.6.2 of RFC 4861 for definition of this option [https://tools.ietf.org/html/rfc4861#section-4.6.2] 173 * 174 */ 175 OT_TOOL_PACKED_BEGIN 176 class PrefixInfoOption : public Option, private Clearable<PrefixInfoOption> 177 { 178 friend class Clearable<PrefixInfoOption>; 179 180 public: 181 static constexpr Type kType = kTypePrefixInfo; ///< Prefix Information Option Type. 182 183 /** 184 * This method initializes the Prefix Info option with proper type and length and sets all other fields to zero. 185 * 186 */ 187 void Init(void); 188 189 /** 190 * This method indicates whether or not the on-link flag is set. 191 * 192 * @retval TRUE The on-link flag is set. 193 * @retval FALSE The on-link flag is not set. 194 * 195 */ IsOnLinkFlagSet(void) const196 bool IsOnLinkFlagSet(void) const { return (mFlags & kOnLinkFlagMask) != 0; } 197 198 /** 199 * This method sets the on-link (L) flag. 200 * 201 */ SetOnLinkFlag(void)202 void SetOnLinkFlag(void) { mFlags |= kOnLinkFlagMask; } 203 204 /** 205 * This method clears the on-link (L) flag. 206 * 207 */ ClearOnLinkFlag(void)208 void ClearOnLinkFlag(void) { mFlags &= ~kOnLinkFlagMask; } 209 210 /** 211 * This method indicates whether or not the autonomous address-configuration (A) flag is set. 212 * 213 * @retval TRUE The auto address-config flag is set. 214 * @retval FALSE The auto address-config flag is not set. 215 * 216 */ IsAutoAddrConfigFlagSet(void) const217 bool IsAutoAddrConfigFlagSet(void) const { return (mFlags & kAutoConfigFlagMask) != 0; } 218 219 /** 220 * This method sets the autonomous address-configuration (A) flag. 221 * 222 */ SetAutoAddrConfigFlag(void)223 void SetAutoAddrConfigFlag(void) { mFlags |= kAutoConfigFlagMask; } 224 225 /** 226 * This method clears the autonomous address-configuration (A) flag. 227 * 228 */ ClearAutoAddrConfigFlag(void)229 void ClearAutoAddrConfigFlag(void) { mFlags &= ~kAutoConfigFlagMask; } 230 231 /** 232 * This method sets the valid lifetime of the prefix in seconds. 233 * 234 * @param[in] aValidLifetime The valid lifetime in seconds. 235 * 236 */ SetValidLifetime(uint32_t aValidLifetime)237 void SetValidLifetime(uint32_t aValidLifetime) { mValidLifetime = HostSwap32(aValidLifetime); } 238 239 /** 240 * THis method gets the valid lifetime of the prefix in seconds. 241 * 242 * @returns The valid lifetime in seconds. 243 * 244 */ GetValidLifetime(void) const245 uint32_t GetValidLifetime(void) const { return HostSwap32(mValidLifetime); } 246 247 /** 248 * This method sets the preferred lifetime of the prefix in seconds. 249 * 250 * @param[in] aPreferredLifetime The preferred lifetime in seconds. 251 * 252 */ SetPreferredLifetime(uint32_t aPreferredLifetime)253 void SetPreferredLifetime(uint32_t aPreferredLifetime) { mPreferredLifetime = HostSwap32(aPreferredLifetime); } 254 255 /** 256 * THis method returns the preferred lifetime of the prefix in seconds. 257 * 258 * @returns The preferred lifetime in seconds. 259 * 260 */ GetPreferredLifetime(void) const261 uint32_t GetPreferredLifetime(void) const { return HostSwap32(mPreferredLifetime); } 262 263 /** 264 * This method sets the prefix. 265 * 266 * @param[in] aPrefix The prefix contained in this option. 267 * 268 */ 269 void SetPrefix(const Prefix &aPrefix); 270 271 /** 272 * This method gets the prefix in this option. 273 * 274 * @param[out] aPrefix Reference to a `Prefix` to return the prefix. 275 * 276 */ 277 void GetPrefix(Prefix &aPrefix) const; 278 279 /** 280 * This method indicates whether or not the option is valid. 281 * 282 * @retval TRUE The option is valid 283 * @retval FALSE The option is not valid. 284 * 285 */ 286 bool IsValid(void) const; 287 288 PrefixInfoOption(void) = delete; 289 290 private: 291 // Prefix Information Option 292 // 293 // 0 1 2 3 294 // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 295 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 296 // | Type | Length | Prefix Length |L|A| Reserved1 | 297 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 298 // | Valid Lifetime | 299 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 300 // | Preferred Lifetime | 301 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 302 // | Reserved2 | 303 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 304 // | | 305 // + + 306 // | | 307 // + Prefix + 308 // | | 309 // + + 310 // | | 311 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 312 313 static constexpr uint8_t kAutoConfigFlagMask = 0x40; // Autonomous address-configuration flag. 314 static constexpr uint8_t kOnLinkFlagMask = 0x80; // On-link flag. 315 316 uint8_t mPrefixLength; // The prefix length in bits. 317 uint8_t mFlags; // The flags field. 318 uint32_t mValidLifetime; // The valid lifetime of the prefix. 319 uint32_t mPreferredLifetime; // The preferred lifetime of the prefix. 320 uint32_t mReserved2; // The reserved field. 321 Address mPrefix; // The prefix. 322 } OT_TOOL_PACKED_END; 323 324 static_assert(sizeof(PrefixInfoOption) == 32, "invalid PrefixInfoOption structure"); 325 326 /** 327 * This class represents the Route Information Option. 328 * 329 * See section 2.3 of RFC 4191 for definition of this option. [https://tools.ietf.org/html/rfc4191#section-2.3] 330 * 331 */ 332 OT_TOOL_PACKED_BEGIN 333 class RouteInfoOption : public Option, private Clearable<RouteInfoOption> 334 { 335 friend class Clearable<RouteInfoOption>; 336 337 public: 338 static constexpr uint16_t kMinSize = kLengthUnit; ///< Minimum size (in bytes) of a Route Info Option 339 static constexpr Type kType = kTypeRouteInfo; ///< Route Information Option Type. 340 341 /** 342 * This method initializes the option setting the type and clearing (setting to zero) all other fields. 343 * 344 */ 345 void Init(void); 346 347 /** 348 * This method sets the route preference. 349 * 350 * @param[in] aPreference The route preference. 351 * 352 */ 353 void SetPreference(RoutePreference aPreference); 354 355 /** 356 * This method gets the route preference. 357 * 358 * @returns The route preference. 359 * 360 */ 361 RoutePreference GetPreference(void) const; 362 363 /** 364 * This method sets the lifetime of the route in seconds. 365 * 366 * @param[in] aLifetime The lifetime of the route in seconds. 367 * 368 */ SetRouteLifetime(uint32_t aLifetime)369 void SetRouteLifetime(uint32_t aLifetime) { mRouteLifetime = HostSwap32(aLifetime); } 370 371 /** 372 * This method gets Route Lifetime in seconds. 373 * 374 * @returns The Route Lifetime in seconds. 375 * 376 */ GetRouteLifetime(void) const377 uint32_t GetRouteLifetime(void) const { return HostSwap32(mRouteLifetime); } 378 379 /** 380 * This method sets the prefix and adjusts the option length based on the prefix length. 381 * 382 * @param[in] aPrefix The prefix contained in this option. 383 * 384 */ 385 void SetPrefix(const Prefix &aPrefix); 386 387 /** 388 * This method gets the prefix in this option. 389 * 390 * @param[out] aPrefix Reference to a `Prefix` to return the prefix. 391 * 392 */ 393 void GetPrefix(Prefix &aPrefix) const; 394 395 /** 396 * This method tells whether this option is valid. 397 * 398 * @returns A boolean indicates whether this option is valid. 399 * 400 */ 401 bool IsValid(void) const; 402 403 /** 404 * This static method calculates the minimum option length for a given prefix length. 405 * 406 * The option length (which is in unit of 8 octets) can be 1, 2, or 3 depending on the prefix length. It can be 1 407 * for a zero prefix length, 2 if the prefix length is not greater than 64, and 3 otherwise. 408 * 409 * @param[in] aPrefixLength The prefix length (in bits). 410 * 411 * @returns The option length (in unit of 8 octet) for @p aPrefixLength. 412 * 413 */ 414 static uint8_t OptionLengthForPrefix(uint8_t aPrefixLength); 415 416 /** 417 * This static method calculates the minimum option size (in bytes) for a given prefix length. 418 * 419 * @param[in] aPrefixLength The prefix length (in bits). 420 * 421 * @returns The option size (in bytes) for @p aPrefixLength. 422 * 423 */ OptionSizeForPrefix(uint8_t aPrefixLength)424 static uint16_t OptionSizeForPrefix(uint8_t aPrefixLength) 425 { 426 return kLengthUnit * OptionLengthForPrefix(aPrefixLength); 427 } 428 429 RouteInfoOption(void) = delete; 430 431 private: 432 // Route Information Option 433 // 434 // 0 1 2 3 435 // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 436 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 437 // | Type | Length | Prefix Length |Resvd|Prf|Resvd| 438 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 439 // | Route Lifetime | 440 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 441 // | Prefix (Variable Length) | 442 // . . 443 // . . 444 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 445 446 static constexpr uint8_t kPreferenceOffset = 3; 447 static constexpr uint8_t kPreferenceMask = 3 << kPreferenceOffset; 448 GetPrefixBytes(void)449 uint8_t *GetPrefixBytes(void) { return AsNonConst(AsConst(this)->GetPrefixBytes()); } GetPrefixBytes(void) const450 const uint8_t *GetPrefixBytes(void) const { return reinterpret_cast<const uint8_t *>(this) + sizeof(*this); } 451 452 uint8_t mPrefixLength; // The prefix length in bits. 453 uint8_t mResvdPrf; // The preference. 454 uint32_t mRouteLifetime; // The lifetime in seconds. 455 // Followed by prefix bytes (variable length). 456 457 } OT_TOOL_PACKED_END; 458 459 static_assert(sizeof(RouteInfoOption) == 8, "invalid RouteInfoOption structure"); 460 461 /** 462 * This class represents a Router Advertisement message. 463 * 464 */ 465 class RouterAdvertMessage 466 { 467 public: 468 /** 469 * This class implements the RA message header. 470 * 471 * See section 2.2 of RFC 4191 [https://datatracker.ietf.org/doc/html/rfc4191] 472 * 473 */ 474 OT_TOOL_PACKED_BEGIN 475 class Header : public Equatable<Header>, private Clearable<Header> 476 { 477 friend class Clearable<Header>; 478 479 public: 480 /** 481 * This constructor initializes the Router Advertisement message with 482 * zero router lifetime, reachable time and retransmission timer. 483 * 484 */ Header(void)485 Header(void) { SetToDefault(); } 486 487 /** 488 * This method sets the RA message to default values. 489 * 490 */ 491 void SetToDefault(void); 492 493 /** 494 * This method sets the checksum value. 495 * 496 * @param[in] aChecksum The checksum value. 497 * 498 */ SetChecksum(uint16_t aChecksum)499 void SetChecksum(uint16_t aChecksum) { mChecksum = HostSwap16(aChecksum); } 500 501 /** 502 * This method sets the Router Lifetime in seconds. 503 * 504 * @param[in] aRouterLifetime The router lifetime in seconds. 505 * 506 */ SetRouterLifetime(uint16_t aRouterLifetime)507 void SetRouterLifetime(uint16_t aRouterLifetime) { mRouterLifetime = HostSwap16(aRouterLifetime); } 508 509 /** 510 * This method gets the Router Lifetime (in seconds). 511 * 512 * Router Lifetime set to zero indicates that the sender is not a default router. 513 * 514 * @returns The router lifetime in seconds. 515 * 516 */ GetRouterLifetime(void) const517 uint16_t GetRouterLifetime(void) const { return HostSwap16(mRouterLifetime); } 518 519 /** 520 * This method sets the default router preference. 521 * 522 * @param[in] aPreference The router preference. 523 * 524 */ 525 void SetDefaultRouterPreference(RoutePreference aPreference); 526 527 /** 528 * This method gets the default router preference. 529 * 530 * @returns The router preference. 531 * 532 */ 533 RoutePreference GetDefaultRouterPreference(void) const; 534 535 private: 536 // Router Advertisement Message 537 // 538 // 0 1 2 3 539 // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 540 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 541 // | Type | Code | Checksum | 542 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 543 // | Cur Hop Limit |M|O|H|Prf|Resvd| Router Lifetime | 544 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 545 // | Reachable Time | 546 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 547 // | Retrans Timer | 548 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 549 // | Options ... 550 // +-+-+-+-+-+-+-+-+-+-+-+- 551 552 static constexpr uint8_t kPreferenceOffset = 3; 553 static constexpr uint8_t kPreferenceMask = 3 << kPreferenceOffset; 554 555 uint8_t mType; 556 uint8_t mCode; 557 uint16_t mChecksum; 558 uint8_t mCurHopLimit; 559 uint8_t mFlags; 560 uint16_t mRouterLifetime; 561 uint32_t mReachableTime; 562 uint32_t mRetransTimer; 563 } OT_TOOL_PACKED_END; 564 565 static_assert(sizeof(Header) == 16, "Invalid RA `Header`"); 566 567 typedef Data<kWithUint16Length> Icmp6Packet; ///< A data buffer containing an ICMPv6 packet. 568 569 /** 570 * This constructor initializes the RA message from a received packet data buffer. 571 * 572 * @param[in] aPacket A received packet data. 573 * 574 */ RouterAdvertMessage(const Icmp6Packet & aPacket)575 explicit RouterAdvertMessage(const Icmp6Packet &aPacket) 576 : mData(aPacket) 577 , mMaxLength(0) 578 { 579 } 580 581 /** 582 * This template constructor initializes the RA message with a given header using a given buffer to store the RA 583 * message. 584 * 585 * @tparam kBufferSize The size of the buffer used to store the RA message. 586 * 587 * @param[in] aHeader The RA message header. 588 * @param[in] aBuffer The data buffer to store the RA message in. 589 * 590 */ 591 template <uint16_t kBufferSize> RouterAdvertMessage(const Header & aHeader,uint8_t (& aBuffer)[kBufferSize])592 RouterAdvertMessage(const Header &aHeader, uint8_t (&aBuffer)[kBufferSize]) 593 : mMaxLength(kBufferSize) 594 { 595 static_assert(kBufferSize >= sizeof(Header), "Buffer for RA msg is too small"); 596 597 memcpy(aBuffer, &aHeader, sizeof(Header)); 598 mData.Init(aBuffer, sizeof(Header)); 599 } 600 601 /** 602 * This method gets the RA message as an `Icmp6Packet`. 603 * 604 * @returns The RA message as an `Icmp6Packet`. 605 * 606 */ GetAsPacket(void) const607 const Icmp6Packet &GetAsPacket(void) const { return mData; } 608 609 /** 610 * This method indicates whether or not the RA message is valid. 611 * 612 * @retval TRUE If the RA message is valid. 613 * @retval FALSE If the RA message is not valid. 614 * 615 */ IsValid(void) const616 bool IsValid(void) const { return (mData.GetBytes() != nullptr) && (mData.GetLength() >= sizeof(Header)); } 617 618 /** 619 * This method gets the RA message's header. 620 * 621 * @returns The RA message's header. 622 * 623 */ GetHeader(void) const624 const Header &GetHeader(void) const { return *reinterpret_cast<const Header *>(mData.GetBytes()); } 625 626 /** 627 * This method appends a Prefix Info Option to the RA message. 628 * 629 * The appended Prefix Info Option will have both on-link (L) and autonomous address-configuration (A) flags set. 630 * 631 * @param[in] aPrefix The prefix. 632 * @param[in] aValidLifetime The valid lifetime in seconds. 633 * @param[in] aPreferredLifetime The preferred lifetime in seconds. 634 * 635 * @retval kErrorNone Option is appended successfully. 636 * @retval kErrorNoBufs No more space in the buffer to append the option. 637 * 638 */ 639 Error AppendPrefixInfoOption(const Prefix &aPrefix, uint32_t aValidLifetime, uint32_t aPreferredLifetime); 640 641 /** 642 * This method appends a Route Info Option to the RA message. 643 * 644 * @param[in] aPrefix The prefix. 645 * @param[in] aRouteLifetime The route lifetime in seconds. 646 * @param[in] aPreference The route preference. 647 * 648 * @retval kErrorNone Option is appended successfully. 649 * @retval kErrorNoBufs No more space in the buffer to append the option. 650 * 651 */ 652 Error AppendRouteInfoOption(const Prefix &aPrefix, uint32_t aRouteLifetime, RoutePreference aPreference); 653 654 /** 655 * This method indicates whether or not the RA message contains any options. 656 * 657 * @retval TRUE If the RA message contains at least one option. 658 * @retval FALSE If the RA message contains no options. 659 * 660 */ ContainsAnyOptions(void) const661 bool ContainsAnyOptions(void) const { return (mData.GetLength() > sizeof(Header)); } 662 663 // The following methods are intended to support range-based `for` 664 // loop iteration over `Option`s in the RA message. 665 begin(void) const666 Option::Iterator begin(void) const { return Option::Iterator(GetOptionStart(), GetDataEnd()); } end(void) const667 Option::Iterator end(void) const { return Option::Iterator(); } 668 669 private: GetOptionStart(void) const670 const uint8_t *GetOptionStart(void) const { return (mData.GetBytes() + sizeof(Header)); } GetDataEnd(void) const671 const uint8_t *GetDataEnd(void) const { return mData.GetBytes() + mData.GetLength(); } 672 Option *AppendOption(uint16_t aOptionSize); 673 674 Data<kWithUint16Length> mData; 675 uint16_t mMaxLength; 676 }; 677 678 /** 679 * This class implements the Router Solicitation message. 680 * 681 * See section 4.1 of RFC 4861 for definition of this message. 682 * https://tools.ietf.org/html/rfc4861#section-4.1 683 * 684 */ 685 OT_TOOL_PACKED_BEGIN 686 class RouterSolicitMessage 687 { 688 public: 689 /** 690 * This constructor initializes the Router Solicitation message. 691 * 692 */ 693 RouterSolicitMessage(void); 694 695 private: 696 Icmp::Header mHeader; // The common ICMPv6 header. 697 } OT_TOOL_PACKED_END; 698 699 static_assert(sizeof(RouterSolicitMessage) == 8, "invalid RouterSolicitMessage structure"); 700 701 /** 702 * This class represents a Neighbor Solicitation (NS) message. 703 * 704 */ 705 OT_TOOL_PACKED_BEGIN 706 class NeighborSolicitMessage : public Clearable<NeighborSolicitMessage> 707 { 708 public: 709 /** 710 * This constructor initializes the Neighbor Solicitation message. 711 * 712 */ 713 NeighborSolicitMessage(void); 714 715 /** 716 * This method indicates whether the Neighbor Solicitation message is valid (proper Type and Code). 717 * 718 * @retval TRUE If the message is valid. 719 * @retval FALSE If the message is not valid. 720 * 721 */ IsValid(void) const722 bool IsValid(void) const { return (mType == Icmp::Header::kTypeNeighborSolicit) && (mCode == 0); } 723 724 /** 725 * This method gets the Target Address field. 726 * 727 * @returns The Target Address. 728 * 729 */ GetTargetAddress(void) const730 const Address &GetTargetAddress(void) const { return mTargetAddress; } 731 732 /** 733 * This method sets the Target Address field. 734 * 735 * @param[in] aTargetAddress The Target Address. 736 * 737 */ SetTargetAddress(const Address & aTargetAddress)738 void SetTargetAddress(const Address &aTargetAddress) { mTargetAddress = aTargetAddress; } 739 740 private: 741 // Neighbor Solicitation Message (RFC 4861) 742 // 743 // 0 1 2 3 744 // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 745 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 746 // | Type | Code | Checksum | 747 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 748 // | Reserved | 749 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 750 // | | 751 // + + 752 // | | 753 // + Target Address + 754 // | | 755 // + + 756 // | | 757 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 758 // | Options ... 759 // +-+-+-+-+-+-+-+-+-+-+-+- 760 761 uint8_t mType; 762 uint8_t mCode; 763 uint16_t mChecksum; 764 uint32_t mReserved; 765 Address mTargetAddress; 766 } OT_TOOL_PACKED_END; 767 768 static_assert(sizeof(NeighborSolicitMessage) == 24, "Invalid NeighborSolicitMessage definition"); 769 770 /** 771 * This class represents a Neighbor Advertisement (NA) message. 772 * 773 */ 774 OT_TOOL_PACKED_BEGIN 775 class NeighborAdvertMessage : public Clearable<NeighborAdvertMessage> 776 { 777 public: 778 NeighborAdvertMessage(void); 779 780 /** 781 * This method indicates whether the Neighbor Advertisement message is valid (proper Type and Code). 782 * 783 * @retval TRUE If the message is valid. 784 * @retval FALSE If the message is not valid. 785 * 786 */ IsValid(void) const787 bool IsValid(void) const { return (mType == Icmp::Header::kTypeNeighborAdvert) && (mCode == 0); } 788 789 /** 790 * This method indicates whether or not the Router Flag is set in the NA message. 791 * 792 * @retval TRUE The Router Flag is set. 793 * @retval FALSE The Router Flag is not set. 794 * 795 */ IsRouterFlagSet(void) const796 bool IsRouterFlagSet(void) const { return (mFlags & kRouterFlag) != 0; } 797 798 /** 799 * This method sets the Router Flag in the NA message. 800 * 801 */ SetRouterFlag(void)802 void SetRouterFlag(void) { mFlags |= kRouterFlag; } 803 804 /** 805 * This method indicates whether or not the Solicited Flag is set in the NA message. 806 * 807 * @retval TRUE The Solicited Flag is set. 808 * @retval FALSE The Solicited Flag is not set. 809 * 810 */ IsSolicitedFlagSet(void) const811 bool IsSolicitedFlagSet(void) const { return (mFlags & kSolicitedFlag) != 0; } 812 813 /** 814 * This method sets the Solicited Flag in the NA message. 815 * 816 */ SetSolicitedFlag(void)817 void SetSolicitedFlag(void) { mFlags |= kSolicitedFlag; } 818 819 /** 820 * This method indicates whether or not the Override Flag is set in the NA message. 821 * 822 * @retval TRUE The Override Flag is set. 823 * @retval FALSE The Override Flag is not set. 824 * 825 */ IsOverrideFlagSet(void) const826 bool IsOverrideFlagSet(void) const { return (mFlags & kOverrideFlag) != 0; } 827 828 /** 829 * This method sets the Override Flag in the NA message. 830 * 831 */ SetOverrideFlag(void)832 void SetOverrideFlag(void) { mFlags |= kOverrideFlag; } 833 834 /** 835 * This method gets the Target Address field. 836 * 837 * @returns The Target Address. 838 * 839 */ GetTargetAddress(void) const840 const Address &GetTargetAddress(void) const { return mTargetAddress; } 841 842 /** 843 * This method sets the Target Address field. 844 * 845 * @param[in] aTargetAddress The Target Address. 846 * 847 */ SetTargetAddress(const Address & aTargetAddress)848 void SetTargetAddress(const Address &aTargetAddress) { mTargetAddress = aTargetAddress; } 849 850 private: 851 // Neighbor Advertisement Message (RFC 4861) 852 // 853 // 0 1 2 3 854 // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 855 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 856 // | Type | Code | Checksum | 857 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 858 // |R|S|O| Reserved | 859 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 860 // | | 861 // + + 862 // | | 863 // + Target Address + 864 // | | 865 // + + 866 // | | 867 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 868 // | Options ... 869 // +-+-+-+-+-+-+-+-+-+-+-+- 870 871 static constexpr uint8_t kRouterFlag = (1 << 7); 872 static constexpr uint8_t kSolicitedFlag = (1 << 6); 873 static constexpr uint8_t kOverrideFlag = (1 << 5); 874 875 uint8_t mType; 876 uint8_t mCode; 877 uint16_t mChecksum; 878 uint8_t mFlags; 879 uint8_t mReserved[3]; 880 Address mTargetAddress; 881 } OT_TOOL_PACKED_END; 882 883 static_assert(sizeof(NeighborAdvertMessage) == 24, "Invalid NeighborAdvertMessage definition"); 884 885 } // namespace Nd 886 } // namespace Ip6 887 } // namespace ot 888 889 #endif // ND6_HPP_ 890