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  * 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      * 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      * 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      * 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      * 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      * 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      * 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      * 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  * 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      * 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      * 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      * Sets the on-link (L) flag.
200      *
201      */
SetOnLinkFlag(void)202     void SetOnLinkFlag(void) { mFlags |= kOnLinkFlagMask; }
203 
204     /**
205      * Clears the on-link (L) flag.
206      *
207      */
ClearOnLinkFlag(void)208     void ClearOnLinkFlag(void) { mFlags &= ~kOnLinkFlagMask; }
209 
210     /**
211      * 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      * Sets the autonomous address-configuration (A) flag.
221      *
222      */
SetAutoAddrConfigFlag(void)223     void SetAutoAddrConfigFlag(void) { mFlags |= kAutoConfigFlagMask; }
224 
225     /**
226      * Clears the autonomous address-configuration (A) flag.
227      *
228      */
ClearAutoAddrConfigFlag(void)229     void ClearAutoAddrConfigFlag(void) { mFlags &= ~kAutoConfigFlagMask; }
230 
231     /**
232      * 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      * 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      * 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      * 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      * 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  * 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      * Initializes the option setting the type and clearing (setting to zero) all other fields.
343      *
344      */
345     void Init(void);
346 
347     /**
348      * Sets the route preference.
349      *
350      * @param[in]  aPreference  The route preference.
351      *
352      */
353     void SetPreference(RoutePreference aPreference);
354 
355     /**
356      * Gets the route preference.
357      *
358      * @returns  The route preference.
359      *
360      */
361     RoutePreference GetPreference(void) const;
362 
363     /**
364      * 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      * 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      * 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      * 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      * 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      * 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      * 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  * Represents a Router Advertisement message.
463  *
464  */
465 class RouterAdvertMessage
466 {
467 public:
468     /**
469      * 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          * 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          * Sets the RA message to default values.
489          *
490          */
491         void SetToDefault(void);
492 
493         /**
494          * 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          * 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          * 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          * Sets the default router preference.
521          *
522          * @param[in]  aPreference  The router preference.
523          *
524          */
525         void SetDefaultRouterPreference(RoutePreference aPreference);
526 
527         /**
528          * Gets the default router preference.
529          *
530          * @returns  The router preference.
531          *
532          */
533         RoutePreference GetDefaultRouterPreference(void) const;
534 
535         /**
536          * This method returns the ICMPv6 message type.
537          *
538          * @returns The ICMPv6 message type.
539          *
540          */
GetType(void) const541         Icmp::Header::Type GetType(void) const { return static_cast<Icmp::Header::Type>(mType); }
542 
543     private:
544         // Router Advertisement Message
545         //
546         //   0                   1                   2                   3
547         //   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
548         //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
549         //  |     Type      |     Code      |          Checksum             |
550         //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
551         //  | Cur Hop Limit |M|O|H|Prf|Resvd|       Router Lifetime         |
552         //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
553         //  |                         Reachable Time                        |
554         //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
555         //  |                          Retrans Timer                        |
556         //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
557         //  |   Options ...
558         //  +-+-+-+-+-+-+-+-+-+-+-+-
559 
560         static constexpr uint8_t kPreferenceOffset = 3;
561         static constexpr uint8_t kPreferenceMask   = 3 << kPreferenceOffset;
562 
563         uint8_t  mType;
564         uint8_t  mCode;
565         uint16_t mChecksum;
566         uint8_t  mCurHopLimit;
567         uint8_t  mFlags;
568         uint16_t mRouterLifetime;
569         uint32_t mReachableTime;
570         uint32_t mRetransTimer;
571     } OT_TOOL_PACKED_END;
572 
573     static_assert(sizeof(Header) == 16, "Invalid RA `Header`");
574 
575     typedef Data<kWithUint16Length> Icmp6Packet; ///< A data buffer containing an ICMPv6 packet.
576 
577     /**
578      * Initializes the RA message from a received packet data buffer.
579      *
580      * @param[in] aPacket   A received packet data.
581      *
582      */
RouterAdvertMessage(const Icmp6Packet & aPacket)583     explicit RouterAdvertMessage(const Icmp6Packet &aPacket)
584         : mData(aPacket)
585         , mMaxLength(0)
586     {
587     }
588 
589     /**
590      * This template constructor initializes the RA message with a given header using a given buffer to store the RA
591      * message.
592      *
593      * @tparam kBufferSize   The size of the buffer used to store the RA message.
594      *
595      * @param[in] aHeader    The RA message header.
596      * @param[in] aBuffer    The data buffer to store the RA message in.
597      *
598      */
599     template <uint16_t kBufferSize>
RouterAdvertMessage(const Header & aHeader,uint8_t (& aBuffer)[kBufferSize])600     RouterAdvertMessage(const Header &aHeader, uint8_t (&aBuffer)[kBufferSize])
601         : mMaxLength(kBufferSize)
602     {
603         static_assert(kBufferSize >= sizeof(Header), "Buffer for RA msg is too small");
604 
605         memcpy(aBuffer, &aHeader, sizeof(Header));
606         mData.Init(aBuffer, sizeof(Header));
607     }
608 
609     /**
610      * Gets the RA message as an `Icmp6Packet`.
611      *
612      * @returns The RA message as an `Icmp6Packet`.
613      *
614      */
GetAsPacket(void) const615     const Icmp6Packet &GetAsPacket(void) const { return mData; }
616 
617     /**
618      * Indicates whether or not the RA message is valid.
619      *
620      * @retval TRUE   If the RA message is valid.
621      * @retval FALSE  If the RA message is not valid.
622      *
623      */
IsValid(void) const624     bool IsValid(void) const
625     {
626         return (mData.GetBytes() != nullptr) && (mData.GetLength() >= sizeof(Header)) &&
627                (GetHeader().GetType() == Icmp::Header::kTypeRouterAdvert);
628     }
629 
630     /**
631      * Gets the RA message's header.
632      *
633      * @returns The RA message's header.
634      *
635      */
GetHeader(void) const636     const Header &GetHeader(void) const { return *reinterpret_cast<const Header *>(mData.GetBytes()); }
637 
638     /**
639      * Appends a Prefix Info Option to the RA message.
640      *
641      * The appended Prefix Info Option will have both on-link (L) and autonomous address-configuration (A) flags set.
642      *
643      * @param[in] aPrefix             The prefix.
644      * @param[in] aValidLifetime      The valid lifetime in seconds.
645      * @param[in] aPreferredLifetime  The preferred lifetime in seconds.
646      *
647      * @retval kErrorNone    Option is appended successfully.
648      * @retval kErrorNoBufs  No more space in the buffer to append the option.
649      *
650      */
651     Error AppendPrefixInfoOption(const Prefix &aPrefix, uint32_t aValidLifetime, uint32_t aPreferredLifetime);
652 
653     /**
654      * Appends a Route Info Option to the RA message.
655      *
656      * @param[in] aPrefix             The prefix.
657      * @param[in] aRouteLifetime      The route lifetime in seconds.
658      * @param[in] aPreference         The route preference.
659      *
660      * @retval kErrorNone    Option is appended successfully.
661      * @retval kErrorNoBufs  No more space in the buffer to append the option.
662      *
663      */
664     Error AppendRouteInfoOption(const Prefix &aPrefix, uint32_t aRouteLifetime, RoutePreference aPreference);
665 
666     /**
667      * Indicates whether or not the RA message contains any options.
668      *
669      * @retval TRUE   If the RA message contains at least one option.
670      * @retval FALSE  If the RA message contains no options.
671      *
672      */
ContainsAnyOptions(void) const673     bool ContainsAnyOptions(void) const { return (mData.GetLength() > sizeof(Header)); }
674 
675     // The following methods are intended to support range-based `for`
676     // loop iteration over `Option`s in the RA message.
677 
begin(void) const678     Option::Iterator begin(void) const { return Option::Iterator(GetOptionStart(), GetDataEnd()); }
end(void) const679     Option::Iterator end(void) const { return Option::Iterator(); }
680 
681 private:
GetOptionStart(void) const682     const uint8_t *GetOptionStart(void) const { return (mData.GetBytes() + sizeof(Header)); }
GetDataEnd(void) const683     const uint8_t *GetDataEnd(void) const { return mData.GetBytes() + mData.GetLength(); }
684     Option        *AppendOption(uint16_t aOptionSize);
685 
686     Data<kWithUint16Length> mData;
687     uint16_t                mMaxLength;
688 };
689 
690 /**
691  * Implements the Router Solicitation message.
692  *
693  * See section 4.1 of RFC 4861 for definition of this message.
694  * https://tools.ietf.org/html/rfc4861#section-4.1
695  *
696  */
697 OT_TOOL_PACKED_BEGIN
698 class RouterSolicitMessage
699 {
700 public:
701     /**
702      * Initializes the Router Solicitation message.
703      *
704      */
705     RouterSolicitMessage(void);
706 
707 private:
708     Icmp::Header mHeader; // The common ICMPv6 header.
709 } OT_TOOL_PACKED_END;
710 
711 static_assert(sizeof(RouterSolicitMessage) == 8, "invalid RouterSolicitMessage structure");
712 
713 /**
714  * Represents a Neighbor Solicitation (NS) message.
715  *
716  */
717 OT_TOOL_PACKED_BEGIN
718 class NeighborSolicitMessage : public Clearable<NeighborSolicitMessage>
719 {
720 public:
721     /**
722      * Initializes the Neighbor Solicitation message.
723      *
724      */
725     NeighborSolicitMessage(void);
726 
727     /**
728      * Indicates whether the Neighbor Solicitation message is valid (proper Type and Code).
729      *
730      * @retval TRUE  If the message is valid.
731      * @retval FALSE If the message is not valid.
732      *
733      */
IsValid(void) const734     bool IsValid(void) const { return (mType == Icmp::Header::kTypeNeighborSolicit) && (mCode == 0); }
735 
736     /**
737      * Gets the Target Address field.
738      *
739      * @returns The Target Address.
740      *
741      */
GetTargetAddress(void) const742     const Address &GetTargetAddress(void) const { return mTargetAddress; }
743 
744     /**
745      * Sets the Target Address field.
746      *
747      * @param[in] aTargetAddress  The Target Address.
748      *
749      */
SetTargetAddress(const Address & aTargetAddress)750     void SetTargetAddress(const Address &aTargetAddress) { mTargetAddress = aTargetAddress; }
751 
752 private:
753     // Neighbor Solicitation Message (RFC 4861)
754     //
755     //   0                   1                   2                   3
756     //   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
757     //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
758     //  |     Type      |     Code      |          Checksum             |
759     //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
760     //  |                           Reserved                            |
761     //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
762     //  |                                                               |
763     //  +                                                               +
764     //  |                                                               |
765     //  +                       Target Address                          +
766     //  |                                                               |
767     //  +                                                               +
768     //  |                                                               |
769     //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
770     //  |   Options ...
771     //  +-+-+-+-+-+-+-+-+-+-+-+-
772 
773     uint8_t  mType;
774     uint8_t  mCode;
775     uint16_t mChecksum;
776     uint32_t mReserved;
777     Address  mTargetAddress;
778 } OT_TOOL_PACKED_END;
779 
780 static_assert(sizeof(NeighborSolicitMessage) == 24, "Invalid NeighborSolicitMessage definition");
781 
782 /**
783  * Represents a Neighbor Advertisement (NA) message.
784  *
785  */
786 OT_TOOL_PACKED_BEGIN
787 class NeighborAdvertMessage : public Clearable<NeighborAdvertMessage>
788 {
789 public:
790     NeighborAdvertMessage(void);
791 
792     /**
793      * Indicates whether the Neighbor Advertisement message is valid (proper Type and Code).
794      *
795      * @retval TRUE  If the message is valid.
796      * @retval FALSE If the message is not valid.
797      *
798      */
IsValid(void) const799     bool IsValid(void) const { return (mType == Icmp::Header::kTypeNeighborAdvert) && (mCode == 0); }
800 
801     /**
802      * Indicates whether or not the Router Flag is set in the NA message.
803      *
804      * @retval TRUE   The Router Flag is set.
805      * @retval FALSE  The Router Flag is not set.
806      *
807      */
IsRouterFlagSet(void) const808     bool IsRouterFlagSet(void) const { return (mFlags & kRouterFlag) != 0; }
809 
810     /**
811      * Sets the Router Flag in the NA message.
812      *
813      */
SetRouterFlag(void)814     void SetRouterFlag(void) { mFlags |= kRouterFlag; }
815 
816     /**
817      * Indicates whether or not the Solicited Flag is set in the NA message.
818      *
819      * @retval TRUE   The Solicited Flag is set.
820      * @retval FALSE  The Solicited Flag is not set.
821      *
822      */
IsSolicitedFlagSet(void) const823     bool IsSolicitedFlagSet(void) const { return (mFlags & kSolicitedFlag) != 0; }
824 
825     /**
826      * Sets the Solicited Flag in the NA message.
827      *
828      */
SetSolicitedFlag(void)829     void SetSolicitedFlag(void) { mFlags |= kSolicitedFlag; }
830 
831     /**
832      * Indicates whether or not the Override Flag is set in the NA message.
833      *
834      * @retval TRUE   The Override Flag is set.
835      * @retval FALSE  The Override Flag is not set.
836      *
837      */
IsOverrideFlagSet(void) const838     bool IsOverrideFlagSet(void) const { return (mFlags & kOverrideFlag) != 0; }
839 
840     /**
841      * Sets the Override Flag in the NA message.
842      *
843      */
SetOverrideFlag(void)844     void SetOverrideFlag(void) { mFlags |= kOverrideFlag; }
845 
846     /**
847      * Gets the Target Address field.
848      *
849      * @returns The Target Address.
850      *
851      */
GetTargetAddress(void) const852     const Address &GetTargetAddress(void) const { return mTargetAddress; }
853 
854     /**
855      * Sets the Target Address field.
856      *
857      * @param[in] aTargetAddress  The Target Address.
858      *
859      */
SetTargetAddress(const Address & aTargetAddress)860     void SetTargetAddress(const Address &aTargetAddress) { mTargetAddress = aTargetAddress; }
861 
862 private:
863     // Neighbor Advertisement Message (RFC 4861)
864     //
865     //   0                   1                   2                   3
866     //   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
867     //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
868     //  |     Type      |     Code      |          Checksum             |
869     //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
870     //  |R|S|O|                     Reserved                            |
871     //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
872     //  |                                                               |
873     //  +                                                               +
874     //  |                                                               |
875     //  +                       Target Address                          +
876     //  |                                                               |
877     //  +                                                               +
878     //  |                                                               |
879     //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
880     //  |   Options ...
881     //  +-+-+-+-+-+-+-+-+-+-+-+-
882 
883     static constexpr uint8_t kRouterFlag    = (1 << 7);
884     static constexpr uint8_t kSolicitedFlag = (1 << 6);
885     static constexpr uint8_t kOverrideFlag  = (1 << 5);
886 
887     uint8_t  mType;
888     uint8_t  mCode;
889     uint16_t mChecksum;
890     uint8_t  mFlags;
891     uint8_t  mReserved[3];
892     Address  mTargetAddress;
893 } OT_TOOL_PACKED_END;
894 
895 static_assert(sizeof(NeighborAdvertMessage) == 24, "Invalid NeighborAdvertMessage definition");
896 
897 } // namespace Nd
898 } // namespace Ip6
899 } // namespace ot
900 
901 #endif // ND6_HPP_
902