• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 public:
179     static constexpr Type kType = kTypePrefixInfo; ///< Prefix Information Option Type.
180 
181     /**
182      * This method initializes the Prefix Info option with proper type and length and sets all other fields to zero.
183      *
184      */
185     void Init(void);
186 
187     /**
188      * This method indicates whether or not the on-link flag is set.
189      *
190      * @retval TRUE  The on-link flag is set.
191      * @retval FALSE The on-link flag is not set.
192      *
193      */
IsOnLinkFlagSet(void) const194     bool IsOnLinkFlagSet(void) const { return (mFlags & kOnLinkFlagMask) != 0; }
195 
196     /**
197      * This method sets the on-link (L) flag.
198      *
199      */
SetOnLinkFlag(void)200     void SetOnLinkFlag(void) { mFlags |= kOnLinkFlagMask; }
201 
202     /**
203      * This method clears the on-link (L) flag.
204      *
205      */
ClearOnLinkFlag(void)206     void ClearOnLinkFlag(void) { mFlags &= ~kOnLinkFlagMask; }
207 
208     /**
209      * This method indicates whether or not the autonomous address-configuration (A) flag is set.
210      *
211      * @retval TRUE  The auto address-config flag is set.
212      * @retval FALSE The auto address-config flag is not set.
213      *
214      */
IsAutoAddrConfigFlagSet(void) const215     bool IsAutoAddrConfigFlagSet(void) const { return (mFlags & kAutoConfigFlagMask) != 0; }
216 
217     /**
218      * This method sets the autonomous address-configuration (A) flag.
219      *
220      */
SetAutoAddrConfigFlag(void)221     void SetAutoAddrConfigFlag(void) { mFlags |= kAutoConfigFlagMask; }
222 
223     /**
224      * This method clears the autonomous address-configuration (A) flag.
225      *
226      */
ClearAutoAddrConfigFlag(void)227     void ClearAutoAddrConfigFlag(void) { mFlags &= ~kAutoConfigFlagMask; }
228 
229     /**
230      * This method sets the valid lifetime of the prefix in seconds.
231      *
232      * @param[in]  aValidLifetime  The valid lifetime in seconds.
233      *
234      */
SetValidLifetime(uint32_t aValidLifetime)235     void SetValidLifetime(uint32_t aValidLifetime) { mValidLifetime = HostSwap32(aValidLifetime); }
236 
237     /**
238      * THis method gets the valid lifetime of the prefix in seconds.
239      *
240      * @returns  The valid lifetime in seconds.
241      *
242      */
GetValidLifetime(void) const243     uint32_t GetValidLifetime(void) const { return HostSwap32(mValidLifetime); }
244 
245     /**
246      * This method sets the preferred lifetime of the prefix in seconds.
247      *
248      * @param[in]  aPreferredLifetime  The preferred lifetime in seconds.
249      *
250      */
SetPreferredLifetime(uint32_t aPreferredLifetime)251     void SetPreferredLifetime(uint32_t aPreferredLifetime) { mPreferredLifetime = HostSwap32(aPreferredLifetime); }
252 
253     /**
254      * THis method returns the preferred lifetime of the prefix in seconds.
255      *
256      * @returns  The preferred lifetime in seconds.
257      *
258      */
GetPreferredLifetime(void) const259     uint32_t GetPreferredLifetime(void) const { return HostSwap32(mPreferredLifetime); }
260 
261     /**
262      * This method sets the prefix.
263      *
264      * @param[in]  aPrefix  The prefix contained in this option.
265      *
266      */
267     void SetPrefix(const Prefix &aPrefix);
268 
269     /**
270      * This method gets the prefix in this option.
271      *
272      * @param[out] aPrefix   Reference to a `Prefix` to return the prefix.
273      *
274      */
275     void GetPrefix(Prefix &aPrefix) const;
276 
277     /**
278      * This method indicates whether or not the option is valid.
279      *
280      * @retval TRUE  The option is valid
281      * @retval FALSE The option is not valid.
282      *
283      */
284     bool IsValid(void) const;
285 
286     PrefixInfoOption(void) = delete;
287 
288 private:
289     // Prefix Information Option
290     //
291     //   0                   1                   2                   3
292     //   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
293     //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
294     //  |     Type      |    Length     | Prefix Length |L|A| Reserved1 |
295     //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
296     //  |                         Valid Lifetime                        |
297     //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
298     //  |                       Preferred Lifetime                      |
299     //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
300     //  |                           Reserved2                           |
301     //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
302     //  |                                                               |
303     //  +                                                               +
304     //  |                                                               |
305     //  +                            Prefix                             +
306     //  |                                                               |
307     //  +                                                               +
308     //  |                                                               |
309     //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
310 
311     static constexpr uint8_t kAutoConfigFlagMask = 0x40; // Autonomous address-configuration flag.
312     static constexpr uint8_t kOnLinkFlagMask     = 0x80; // On-link flag.
313 
314     uint8_t  mPrefixLength;      // The prefix length in bits.
315     uint8_t  mFlags;             // The flags field.
316     uint32_t mValidLifetime;     // The valid lifetime of the prefix.
317     uint32_t mPreferredLifetime; // The preferred lifetime of the prefix.
318     uint32_t mReserved2;         // The reserved field.
319     Address  mPrefix;            // The prefix.
320 } OT_TOOL_PACKED_END;
321 
322 static_assert(sizeof(PrefixInfoOption) == 32, "invalid PrefixInfoOption structure");
323 
324 /**
325  * This class represents the Route Information Option.
326  *
327  * See section 2.3 of RFC 4191 for definition of this option. [https://tools.ietf.org/html/rfc4191#section-2.3]
328  *
329  */
330 OT_TOOL_PACKED_BEGIN
331 class RouteInfoOption : public Option, private Clearable<RouteInfoOption>
332 {
333 public:
334     static constexpr uint16_t kMinSize = kLengthUnit;    ///< Minimum size (in bytes) of a Route Info Option
335     static constexpr Type     kType    = kTypeRouteInfo; ///< Route Information Option Type.
336 
337     /**
338      * This method initializes the option setting the type and clearing (setting to zero) all other fields.
339      *
340      */
341     void Init(void);
342 
343     /**
344      * This method sets the route preference.
345      *
346      * @param[in]  aPreference  The route preference.
347      *
348      */
349     void SetPreference(RoutePreference aPreference);
350 
351     /**
352      * This method gets the route preference.
353      *
354      * @returns  The route preference.
355      *
356      */
357     RoutePreference GetPreference(void) const;
358 
359     /**
360      * This method sets the lifetime of the route in seconds.
361      *
362      * @param[in]  aLifetime  The lifetime of the route in seconds.
363      *
364      */
SetRouteLifetime(uint32_t aLifetime)365     void SetRouteLifetime(uint32_t aLifetime) { mRouteLifetime = HostSwap32(aLifetime); }
366 
367     /**
368      * This method gets Route Lifetime in seconds.
369      *
370      * @returns  The Route Lifetime in seconds.
371      *
372      */
GetRouteLifetime(void) const373     uint32_t GetRouteLifetime(void) const { return HostSwap32(mRouteLifetime); }
374 
375     /**
376      * This method sets the prefix and adjusts the option length based on the prefix length.
377      *
378      * @param[in]  aPrefix  The prefix contained in this option.
379      *
380      */
381     void SetPrefix(const Prefix &aPrefix);
382 
383     /**
384      * This method gets the prefix in this option.
385      *
386      * @param[out] aPrefix   Reference to a `Prefix` to return the prefix.
387      *
388      */
389     void GetPrefix(Prefix &aPrefix) const;
390 
391     /**
392      * This method tells whether this option is valid.
393      *
394      * @returns  A boolean indicates whether this option is valid.
395      *
396      */
397     bool IsValid(void) const;
398 
399     /**
400      * This static method calculates the minimum option length for a given prefix length.
401      *
402      * 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
403      * for a zero prefix length, 2 if the prefix length is not greater than 64, and 3 otherwise.
404      *
405      * @param[in] aPrefixLength   The prefix length (in bits).
406      *
407      * @returns The option length (in unit of 8 octet) for @p aPrefixLength.
408      *
409      */
410     static uint8_t OptionLengthForPrefix(uint8_t aPrefixLength);
411 
412     /**
413      * This static method calculates the minimum option size (in bytes) for a given prefix length.
414      *
415      * @param[in] aPrefixLength   The prefix length (in bits).
416      *
417      * @returns The option size (in bytes) for @p aPrefixLength.
418      *
419      */
OptionSizeForPrefix(uint8_t aPrefixLength)420     static uint16_t OptionSizeForPrefix(uint8_t aPrefixLength)
421     {
422         return kLengthUnit * OptionLengthForPrefix(aPrefixLength);
423     }
424 
425     RouteInfoOption(void) = delete;
426 
427 private:
428     // Route Information Option
429     //
430     //   0                   1                   2                   3
431     //   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
432     //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
433     //  |     Type      |    Length     | Prefix Length |Resvd|Prf|Resvd|
434     //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
435     //  |                        Route Lifetime                         |
436     //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
437     //  |                   Prefix (Variable Length)                    |
438     //  .                                                               .
439     //  .                                                               .
440     //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
441 
442     static constexpr uint8_t kPreferenceOffset = 3;
443     static constexpr uint8_t kPreferenceMask   = 3 << kPreferenceOffset;
444 
GetPrefixBytes(void)445     uint8_t *      GetPrefixBytes(void) { return AsNonConst(AsConst(this)->GetPrefixBytes()); }
GetPrefixBytes(void) const446     const uint8_t *GetPrefixBytes(void) const { return reinterpret_cast<const uint8_t *>(this) + sizeof(*this); }
447 
448     uint8_t  mPrefixLength;  // The prefix length in bits.
449     uint8_t  mResvdPrf;      // The preference.
450     uint32_t mRouteLifetime; // The lifetime in seconds.
451     // Followed by prefix bytes (variable length).
452 
453 } OT_TOOL_PACKED_END;
454 
455 static_assert(sizeof(RouteInfoOption) == 8, "invalid RouteInfoOption structure");
456 
457 /**
458  * This class represents a Router Advertisement message.
459  *
460  */
461 class RouterAdvertMessage
462 {
463 public:
464     /**
465      * This class implements the RA message header.
466      *
467      * See section 2.2 of RFC 4191 [https://datatracker.ietf.org/doc/html/rfc4191]
468      *
469      */
470     OT_TOOL_PACKED_BEGIN
471     class Header : public Equatable<Header>, private Clearable<Header>
472     {
473     public:
474         /**
475          * This constructor initializes the Router Advertisement message with
476          * zero router lifetime, reachable time and retransmission timer.
477          *
478          */
Header(void)479         Header(void) { SetToDefault(); }
480 
481         /**
482          * This method sets the RA message to default values.
483          *
484          */
485         void SetToDefault(void);
486 
487         /**
488          * This method sets the checksum value.
489          *
490          * @param[in]  aChecksum  The checksum value.
491          *
492          */
SetChecksum(uint16_t aChecksum)493         void SetChecksum(uint16_t aChecksum) { mChecksum = HostSwap16(aChecksum); }
494 
495         /**
496          * This method sets the Router Lifetime in seconds.
497          *
498          * @param[in]  aRouterLifetime  The router lifetime in seconds.
499          *
500          */
SetRouterLifetime(uint16_t aRouterLifetime)501         void SetRouterLifetime(uint16_t aRouterLifetime) { mRouterLifetime = HostSwap16(aRouterLifetime); }
502 
503         /**
504          * This method gets the Router Lifetime (in seconds).
505          *
506          * Router Lifetime set to zero indicates that the sender is not a default router.
507          *
508          * @returns  The router lifetime in seconds.
509          *
510          */
GetRouterLifetime(void) const511         uint16_t GetRouterLifetime(void) const { return HostSwap16(mRouterLifetime); }
512 
513         /**
514          * This method sets the default router preference.
515          *
516          * @param[in]  aPreference  The router preference.
517          *
518          */
519         void SetDefaultRouterPreference(RoutePreference aPreference);
520 
521         /**
522          * This method gets the default router preference.
523          *
524          * @returns  The router preference.
525          *
526          */
527         RoutePreference GetDefaultRouterPreference(void) const;
528 
529     private:
530         // Router Advertisement Message
531         //
532         //   0                   1                   2                   3
533         //   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
534         //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
535         //  |     Type      |     Code      |          Checksum             |
536         //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
537         //  | Cur Hop Limit |M|O|H|Prf|Resvd|       Router Lifetime         |
538         //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
539         //  |                         Reachable Time                        |
540         //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
541         //  |                          Retrans Timer                        |
542         //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
543         //  |   Options ...
544         //  +-+-+-+-+-+-+-+-+-+-+-+-
545 
546         static constexpr uint8_t kPreferenceOffset = 3;
547         static constexpr uint8_t kPreferenceMask   = 3 << kPreferenceOffset;
548 
549         uint8_t  mType;
550         uint8_t  mCode;
551         uint16_t mChecksum;
552         uint8_t  mCurHopLimit;
553         uint8_t  mFlags;
554         uint16_t mRouterLifetime;
555         uint32_t mReachableTime;
556         uint32_t mRetransTimer;
557     } OT_TOOL_PACKED_END;
558 
559     static_assert(sizeof(Header) == 16, "Invalid RA `Header`");
560 
561     typedef Data<kWithUint16Length> Icmp6Packet; ///< A data buffer containing an ICMPv6 packet.
562 
563     /**
564      * This constructor initializes the RA message from a received packet data buffer.
565      *
566      * @param[in] aPacket   A received packet data.
567      *
568      */
RouterAdvertMessage(const Icmp6Packet & aPacket)569     explicit RouterAdvertMessage(const Icmp6Packet &aPacket)
570         : mData(aPacket)
571         , mMaxLength(0)
572     {
573     }
574 
575     /**
576      * This template constructor initializes the RA message with a given header using a given buffer to store the RA
577      * message.
578      *
579      * @tparam kBufferSize   The size of the buffer used to store the RA message.
580      *
581      * @param[in] aHeader    The RA message header.
582      * @param[in] aBuffer    The data buffer to store the RA message in.
583      *
584      */
585     template <uint16_t kBufferSize>
RouterAdvertMessage(const Header & aHeader,uint8_t (& aBuffer)[kBufferSize])586     RouterAdvertMessage(const Header &aHeader, uint8_t (&aBuffer)[kBufferSize])
587         : mMaxLength(kBufferSize)
588     {
589         static_assert(kBufferSize >= sizeof(Header), "Buffer for RA msg is too small");
590 
591         memcpy(aBuffer, &aHeader, sizeof(Header));
592         mData.Init(aBuffer, sizeof(Header));
593     }
594 
595     /**
596      * This method gets the RA message as an `Icmp6Packet`.
597      *
598      * @returns The RA message as an `Icmp6Packet`.
599      *
600      */
GetAsPacket(void) const601     const Icmp6Packet &GetAsPacket(void) const { return mData; }
602 
603     /**
604      * This method indicates whether or not the RA message is valid.
605      *
606      * @retval TRUE   If the RA message is valid.
607      * @retval FALSE  If the RA message is not valid.
608      *
609      */
IsValid(void) const610     bool IsValid(void) const { return (mData.GetBytes() != nullptr) && (mData.GetLength() >= sizeof(Header)); }
611 
612     /**
613      * This method gets the RA message's header.
614      *
615      * @returns The RA message's header.
616      *
617      */
GetHeader(void) const618     const Header &GetHeader(void) const { return *reinterpret_cast<const Header *>(mData.GetBytes()); }
619 
620     /**
621      * This method appends a Prefix Info Option to the RA message.
622      *
623      * The appended Prefix Info Option will have both on-link (L) and autonomous address-configuration (A) flags set.
624      *
625      * @param[in] aPrefix             The prefix.
626      * @param[in] aValidLifetime      The valid lifetime in seconds.
627      * @param[in] aPreferredLifetime  The preferred lifetime in seconds.
628      *
629      * @retval kErrorNone    Option is appended successfully.
630      * @retval kErrorNoBufs  No more space in the buffer to append the option.
631      *
632      */
633     Error AppendPrefixInfoOption(const Prefix &aPrefix, uint32_t aValidLifetime, uint32_t aPreferredLifetime);
634 
635     /**
636      * This method appends a Route Info Option to the RA message.
637      *
638      * @param[in] aPrefix             The prefix.
639      * @param[in] aRouteLifetime      The route lifetime in seconds.
640      * @param[in] aPreference         The route preference.
641      *
642      * @retval kErrorNone    Option is appended successfully.
643      * @retval kErrorNoBufs  No more space in the buffer to append the option.
644      *
645      */
646     Error AppendRouteInfoOption(const Prefix &aPrefix, uint32_t aRouteLifetime, RoutePreference aPreference);
647 
648     /**
649      * This method indicates whether or not the RA message contains any options.
650      *
651      * @retval TRUE   If the RA message contains at least one option.
652      * @retval FALSE  If the RA message contains no options.
653      *
654      */
ContainsAnyOptions(void) const655     bool ContainsAnyOptions(void) const { return (mData.GetLength() > sizeof(Header)); }
656 
657     // The following methods are intended to support range-based `for`
658     // loop iteration over `Option`s in the RA message.
659 
begin(void) const660     Option::Iterator begin(void) const { return Option::Iterator(GetOptionStart(), GetDataEnd()); }
end(void) const661     Option::Iterator end(void) const { return Option::Iterator(); }
662 
663 private:
GetOptionStart(void) const664     const uint8_t *GetOptionStart(void) const { return (mData.GetBytes() + sizeof(Header)); }
GetDataEnd(void) const665     const uint8_t *GetDataEnd(void) const { return mData.GetBytes() + mData.GetLength(); }
666     Option *       AppendOption(uint16_t aOptionSize);
667 
668     Data<kWithUint16Length> mData;
669     uint16_t                mMaxLength;
670 };
671 
672 /**
673  * This class implements the Router Solicitation message.
674  *
675  * See section 4.1 of RFC 4861 for definition of this message.
676  * https://tools.ietf.org/html/rfc4861#section-4.1
677  *
678  */
679 OT_TOOL_PACKED_BEGIN
680 class RouterSolicitMessage
681 {
682 public:
683     /**
684      * This constructor initializes the Router Solicitation message.
685      *
686      */
687     RouterSolicitMessage(void);
688 
689 private:
690     Icmp::Header mHeader; // The common ICMPv6 header.
691 } OT_TOOL_PACKED_END;
692 
693 static_assert(sizeof(RouterSolicitMessage) == 8, "invalid RouterSolicitMessage structure");
694 
695 } // namespace Nd
696 } // namespace Ip6
697 } // namespace ot
698 
699 #endif // ND6_HPP_
700