• 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 "common/heap_array.hpp"
51 #include "net/icmp6.hpp"
52 #include "net/ip6.hpp"
53 #include "thread/network_data_types.hpp"
54 
55 namespace ot {
56 namespace Ip6 {
57 namespace Nd {
58 
59 typedef NetworkData::RoutePreference RoutePreference; ///< Route Preference
60 
61 /**
62  * Represents the variable length options in Neighbor Discovery messages.
63  *
64  * @sa PrefixInfoOption
65  * @sa RouteInfoOption
66  *
67  */
68 OT_TOOL_PACKED_BEGIN
69 class Option
70 {
71     friend class RouterAdvert;
72 
73 public:
74     enum Type : uint8_t
75     {
76         kTypePrefixInfo       = 3,  ///< Prefix Information Option.
77         kTypeRouteInfo        = 24, ///< Route Information Option.
78         kTypeRaFlagsExtension = 26, ///< RA Flags Extension Option.
79     };
80 
81     static constexpr uint16_t kLengthUnit = 8; ///< The unit of length in octets.
82 
83     /**
84      * Gets the option type.
85      *
86      * @returns  The option type.
87      *
88      */
GetType(void) const89     uint8_t GetType(void) const { return mType; }
90 
91     /**
92      * Sets the option type.
93      *
94      * @param[in] aType  The option type.
95      *
96      *
97      */
SetType(Type aType)98     void SetType(Type aType) { mType = aType; }
99 
100     /**
101      * Sets the length based on a given total option size in bytes.
102      *
103      * Th option must end on a 64-bit boundary, so the length is derived as `(aSize + 7) / 8 * 8`.
104      *
105      * @param[in]  aSize  The size of option in bytes.
106      *
107      */
SetSize(uint16_t aSize)108     void SetSize(uint16_t aSize) { mLength = static_cast<uint8_t>((aSize + kLengthUnit - 1) / kLengthUnit); }
109 
110     /**
111      * Returns the size of the option in bytes.
112      *
113      * @returns  The size of the option in bytes.
114      *
115      */
GetSize(void) const116     uint16_t GetSize(void) const { return mLength * kLengthUnit; }
117 
118     /**
119      * Sets the length of the option (in unit of 8 bytes).
120      *
121      * @param[in]  aLength  The length of the option in unit of 8 bytes.
122      *
123      */
SetLength(uint8_t aLength)124     void SetLength(uint8_t aLength) { mLength = aLength; }
125 
126     /**
127      * Returns the length of the option (in unit of 8 bytes).
128      *
129      * @returns  The length of the option in unit of 8 bytes.
130      *
131      */
GetLength(void) const132     uint16_t GetLength(void) const { return mLength; }
133 
134     /**
135      * Indicates whether or not this option is valid.
136      *
137      * @retval TRUE   The option is valid.
138      * @retval FALSE  The option is not valid.
139      *
140      */
IsValid(void) const141     bool IsValid(void) const { return mLength > 0; }
142 
143 private:
144     class Iterator : public Unequatable<Iterator>
145     {
146     public:
147         Iterator(void);
148         Iterator(const void *aStart, const void *aEnd);
149 
operator *(void)150         const Option &operator*(void) { return *mOption; }
operator ++(void)151         void          operator++(void) { Advance(); }
operator ++(int)152         void          operator++(int) { Advance(); }
operator ==(const Iterator & aOther) const153         bool          operator==(const Iterator &aOther) const { return mOption == aOther.mOption; }
154 
155     private:
156         static const Option *Next(const Option *aOption);
157         void                 Advance(void);
158         const Option        *Validate(const Option *aOption) const;
159 
160         const Option *mOption;
161         const Option *mEnd;
162     };
163 
164     uint8_t mType;   // Type of the option.
165     uint8_t mLength; // Length of the option in unit of 8 octets, including the `mType` and `mLength` fields.
166 } OT_TOOL_PACKED_END;
167 
168 /**
169  * Represents the Prefix Information Option.
170  *
171  * See section 4.6.2 of RFC 4861 for definition of this option [https://tools.ietf.org/html/rfc4861#section-4.6.2]
172  *
173  */
174 OT_TOOL_PACKED_BEGIN
175 class PrefixInfoOption : public Option, private Clearable<PrefixInfoOption>
176 {
177     friend class Clearable<PrefixInfoOption>;
178 
179 public:
180     static constexpr Type kType = kTypePrefixInfo; ///< Prefix Information Option Type.
181 
182     /**
183      * Initializes the Prefix Info option with proper type and length and sets all other fields to zero.
184      *
185      */
186     void Init(void);
187 
188     /**
189      * Indicates whether or not the on-link flag is set.
190      *
191      * @retval TRUE  The on-link flag is set.
192      * @retval FALSE The on-link flag is not set.
193      *
194      */
IsOnLinkFlagSet(void) const195     bool IsOnLinkFlagSet(void) const { return (mFlags & kOnLinkFlagMask) != 0; }
196 
197     /**
198      * Sets the on-link (L) flag.
199      *
200      */
SetOnLinkFlag(void)201     void SetOnLinkFlag(void) { mFlags |= kOnLinkFlagMask; }
202 
203     /**
204      * Clears the on-link (L) flag.
205      *
206      */
ClearOnLinkFlag(void)207     void ClearOnLinkFlag(void) { mFlags &= ~kOnLinkFlagMask; }
208 
209     /**
210      * Indicates whether or not the autonomous address-configuration (A) flag is set.
211      *
212      * @retval TRUE  The auto address-config flag is set.
213      * @retval FALSE The auto address-config flag is not set.
214      *
215      */
IsAutoAddrConfigFlagSet(void) const216     bool IsAutoAddrConfigFlagSet(void) const { return (mFlags & kAutoConfigFlagMask) != 0; }
217 
218     /**
219      * Sets the autonomous address-configuration (A) flag.
220      *
221      */
SetAutoAddrConfigFlag(void)222     void SetAutoAddrConfigFlag(void) { mFlags |= kAutoConfigFlagMask; }
223 
224     /**
225      * Clears the autonomous address-configuration (A) flag.
226      *
227      */
ClearAutoAddrConfigFlag(void)228     void ClearAutoAddrConfigFlag(void) { mFlags &= ~kAutoConfigFlagMask; }
229 
230     /**
231      * Sets the valid lifetime of the prefix in seconds.
232      *
233      * @param[in]  aValidLifetime  The valid lifetime in seconds.
234      *
235      */
SetValidLifetime(uint32_t aValidLifetime)236     void SetValidLifetime(uint32_t aValidLifetime) { mValidLifetime = BigEndian::HostSwap32(aValidLifetime); }
237 
238     /**
239      * THis method gets the valid lifetime of the prefix in seconds.
240      *
241      * @returns  The valid lifetime in seconds.
242      *
243      */
GetValidLifetime(void) const244     uint32_t GetValidLifetime(void) const { return BigEndian::HostSwap32(mValidLifetime); }
245 
246     /**
247      * Sets the preferred lifetime of the prefix in seconds.
248      *
249      * @param[in]  aPreferredLifetime  The preferred lifetime in seconds.
250      *
251      */
SetPreferredLifetime(uint32_t aPreferredLifetime)252     void SetPreferredLifetime(uint32_t aPreferredLifetime)
253     {
254         mPreferredLifetime = BigEndian::HostSwap32(aPreferredLifetime);
255     }
256 
257     /**
258      * THis method returns the preferred lifetime of the prefix in seconds.
259      *
260      * @returns  The preferred lifetime in seconds.
261      *
262      */
GetPreferredLifetime(void) const263     uint32_t GetPreferredLifetime(void) const { return BigEndian::HostSwap32(mPreferredLifetime); }
264 
265     /**
266      * Sets the prefix.
267      *
268      * @param[in]  aPrefix  The prefix contained in this option.
269      *
270      */
271     void SetPrefix(const Prefix &aPrefix);
272 
273     /**
274      * Gets the prefix in this option.
275      *
276      * @param[out] aPrefix   Reference to a `Prefix` to return the prefix.
277      *
278      */
279     void GetPrefix(Prefix &aPrefix) const;
280 
281     /**
282      * Indicates whether or not the option is valid.
283      *
284      * @retval TRUE  The option is valid
285      * @retval FALSE The option is not valid.
286      *
287      */
288     bool IsValid(void) const;
289 
290     PrefixInfoOption(void) = delete;
291 
292 private:
293     // Prefix Information Option
294     //
295     //   0                   1                   2                   3
296     //   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
297     //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
298     //  |     Type      |    Length     | Prefix Length |L|A| Reserved1 |
299     //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
300     //  |                         Valid Lifetime                        |
301     //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
302     //  |                       Preferred Lifetime                      |
303     //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
304     //  |                           Reserved2                           |
305     //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
306     //  |                                                               |
307     //  +                                                               +
308     //  |                                                               |
309     //  +                            Prefix                             +
310     //  |                                                               |
311     //  +                                                               +
312     //  |                                                               |
313     //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
314 
315     static constexpr uint8_t kAutoConfigFlagMask = 0x40; // Autonomous address-configuration flag.
316     static constexpr uint8_t kOnLinkFlagMask     = 0x80; // On-link flag.
317 
318     uint8_t  mPrefixLength;      // The prefix length in bits.
319     uint8_t  mFlags;             // The flags field.
320     uint32_t mValidLifetime;     // The valid lifetime of the prefix.
321     uint32_t mPreferredLifetime; // The preferred lifetime of the prefix.
322     uint32_t mReserved2;         // The reserved field.
323     Address  mPrefix;            // The prefix.
324 } OT_TOOL_PACKED_END;
325 
326 static_assert(sizeof(PrefixInfoOption) == 32, "invalid PrefixInfoOption structure");
327 
328 /**
329  * Represents the Route Information Option.
330  *
331  * See section 2.3 of RFC 4191 for definition of this option. [https://tools.ietf.org/html/rfc4191#section-2.3]
332  *
333  */
334 OT_TOOL_PACKED_BEGIN
335 class RouteInfoOption : public Option, private Clearable<RouteInfoOption>
336 {
337     friend class Clearable<RouteInfoOption>;
338 
339 public:
340     static constexpr uint16_t kMinSize = kLengthUnit;    ///< Minimum size (in bytes) of a Route Info Option
341     static constexpr Type     kType    = kTypeRouteInfo; ///< Route Information Option Type.
342 
343     /**
344      * Initializes the option setting the type and clearing (setting to zero) all other fields.
345      *
346      */
347     void Init(void);
348 
349     /**
350      * Sets the route preference.
351      *
352      * @param[in]  aPreference  The route preference.
353      *
354      */
355     void SetPreference(RoutePreference aPreference);
356 
357     /**
358      * Gets the route preference.
359      *
360      * @returns  The route preference.
361      *
362      */
363     RoutePreference GetPreference(void) const;
364 
365     /**
366      * Sets the lifetime of the route in seconds.
367      *
368      * @param[in]  aLifetime  The lifetime of the route in seconds.
369      *
370      */
SetRouteLifetime(uint32_t aLifetime)371     void SetRouteLifetime(uint32_t aLifetime) { mRouteLifetime = BigEndian::HostSwap32(aLifetime); }
372 
373     /**
374      * Gets Route Lifetime in seconds.
375      *
376      * @returns  The Route Lifetime in seconds.
377      *
378      */
GetRouteLifetime(void) const379     uint32_t GetRouteLifetime(void) const { return BigEndian::HostSwap32(mRouteLifetime); }
380 
381     /**
382      * Sets the prefix and adjusts the option length based on the prefix length.
383      *
384      * @param[in]  aPrefix  The prefix contained in this option.
385      *
386      */
387     void SetPrefix(const Prefix &aPrefix);
388 
389     /**
390      * Gets the prefix in this option.
391      *
392      * @param[out] aPrefix   Reference to a `Prefix` to return the prefix.
393      *
394      */
395     void GetPrefix(Prefix &aPrefix) const;
396 
397     /**
398      * Tells whether this option is valid.
399      *
400      * @returns  A boolean indicates whether this option is valid.
401      *
402      */
403     bool IsValid(void) const;
404 
405     /**
406      * Calculates the minimum option length for a given prefix length.
407      *
408      * 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
409      * for a zero prefix length, 2 if the prefix length is not greater than 64, and 3 otherwise.
410      *
411      * @param[in] aPrefixLength   The prefix length (in bits).
412      *
413      * @returns The option length (in unit of 8 octet) for @p aPrefixLength.
414      *
415      */
416     static uint8_t OptionLengthForPrefix(uint8_t aPrefixLength);
417 
418     /**
419      * Calculates the minimum option size (in bytes) for a given prefix length.
420      *
421      * @param[in] aPrefixLength   The prefix length (in bits).
422      *
423      * @returns The option size (in bytes) for @p aPrefixLength.
424      *
425      */
OptionSizeForPrefix(uint8_t aPrefixLength)426     static uint16_t OptionSizeForPrefix(uint8_t aPrefixLength)
427     {
428         return kLengthUnit * OptionLengthForPrefix(aPrefixLength);
429     }
430 
431     RouteInfoOption(void) = delete;
432 
433 private:
434     // Route Information Option
435     //
436     //   0                   1                   2                   3
437     //   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
438     //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
439     //  |     Type      |    Length     | Prefix Length |Resvd|Prf|Resvd|
440     //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
441     //  |                        Route Lifetime                         |
442     //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
443     //  |                   Prefix (Variable Length)                    |
444     //  .                                                               .
445     //  .                                                               .
446     //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
447 
448     static constexpr uint8_t kPreferenceOffset = 3;
449     static constexpr uint8_t kPreferenceMask   = 3 << kPreferenceOffset;
450 
GetPrefixBytes(void)451     uint8_t       *GetPrefixBytes(void) { return AsNonConst(AsConst(this)->GetPrefixBytes()); }
GetPrefixBytes(void) const452     const uint8_t *GetPrefixBytes(void) const { return reinterpret_cast<const uint8_t *>(this) + sizeof(*this); }
453 
454     uint8_t  mPrefixLength;  // The prefix length in bits.
455     uint8_t  mResvdPrf;      // The preference.
456     uint32_t mRouteLifetime; // The lifetime in seconds.
457     // Followed by prefix bytes (variable length).
458 
459 } OT_TOOL_PACKED_END;
460 
461 static_assert(sizeof(RouteInfoOption) == 8, "invalid RouteInfoOption structure");
462 
463 /**
464  * Represents an RA Flags Extension Option.
465  *
466  * See RFC-5175 [https://tools.ietf.org/html/rfc5175]
467  *
468  */
469 OT_TOOL_PACKED_BEGIN
470 class RaFlagsExtOption : public Option, private Clearable<RaFlagsExtOption>
471 {
472     friend class Clearable<RaFlagsExtOption>;
473 
474 public:
475     static constexpr Type kType = kTypeRaFlagsExtension; ///< RA Flags Extension Option type.
476 
477     /**
478      * Initializes the RA Flags Extension option with proper type and length and sets all flags to zero.
479      *
480      */
481     void Init(void);
482 
483     /**
484      * Tells whether this option is valid.
485      *
486      * @returns  A boolean indicates whether this option is valid.
487      *
488      */
IsValid(void) const489     bool IsValid(void) const { return GetSize() >= sizeof(*this); }
490 
491     /**
492      * Indicates whether or not the Stub Router Flag is set.
493      *
494      * @retval TRUE   The Stub Router Flag is set.
495      * @retval FALSE  The Stub Router Flag is not set.
496      *
497      */
IsStubRouterFlagSet(void) const498     bool IsStubRouterFlagSet(void) const { return (mFlags[0] & kStubRouterFlag) != 0; }
499 
500     /**
501      * Sets the Stub Router Flag.
502      *
503      */
SetStubRouterFlag(void)504     void SetStubRouterFlag(void) { mFlags[0] |= kStubRouterFlag; }
505 
506     RaFlagsExtOption(void) = delete;
507 
508 private:
509     // RA Flags Extension Option
510     //
511     //   0                   1                   2                   3
512     //   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
513     //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
514     //  |     Type      |    Length     |         Bit fields available ..
515     //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
516     //  ... for assignment                                              |
517     //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+                                .
518 
519     // Stub router flags defined in [https://www.ietf.org/archive/id/draft-hui-stub-router-ra-flag-01.txt]
520 
521     static constexpr uint8_t kStubRouterFlag = 1 << 7;
522 
523     uint8_t mFlags[6];
524 } OT_TOOL_PACKED_END;
525 
526 static_assert(sizeof(RaFlagsExtOption) == 8, "invalid RaFlagsExtOption structure");
527 
528 /**
529  * Defines Router Advertisement components.
530  *
531  */
532 class RouterAdvert
533 {
534 public:
535     /**
536      * Represent an RA message header.
537      *
538      * See section 2.2 of RFC 4191 [https://datatracker.ietf.org/doc/html/rfc4191]
539      *
540      */
541     OT_TOOL_PACKED_BEGIN
542     class Header : public Equatable<Header>, private Clearable<Header>
543     {
544         friend class Clearable<Header>;
545 
546     public:
547         /**
548          * Initializes the Router Advertisement message with
549          * zero router lifetime, reachable time and retransmission timer.
550          *
551          */
Header(void)552         Header(void) { SetToDefault(); }
553 
554         /**
555          * Sets the RA message to default values.
556          *
557          */
558         void SetToDefault(void);
559 
560         /**
561          * Sets the checksum value.
562          *
563          * @param[in]  aChecksum  The checksum value.
564          *
565          */
SetChecksum(uint16_t aChecksum)566         void SetChecksum(uint16_t aChecksum) { mChecksum = BigEndian::HostSwap16(aChecksum); }
567 
568         /**
569          * Sets the Router Lifetime in seconds.
570          *
571          * @param[in]  aRouterLifetime  The router lifetime in seconds.
572          *
573          */
SetRouterLifetime(uint16_t aRouterLifetime)574         void SetRouterLifetime(uint16_t aRouterLifetime) { mRouterLifetime = BigEndian::HostSwap16(aRouterLifetime); }
575 
576         /**
577          * Gets the Router Lifetime (in seconds).
578          *
579          * Router Lifetime set to zero indicates that the sender is not a default router.
580          *
581          * @returns  The router lifetime in seconds.
582          *
583          */
GetRouterLifetime(void) const584         uint16_t GetRouterLifetime(void) const { return BigEndian::HostSwap16(mRouterLifetime); }
585 
586         /**
587          * Sets the default router preference.
588          *
589          * @param[in]  aPreference  The router preference.
590          *
591          */
592         void SetDefaultRouterPreference(RoutePreference aPreference);
593 
594         /**
595          * Gets the default router preference.
596          *
597          * @returns  The router preference.
598          *
599          */
600         RoutePreference GetDefaultRouterPreference(void) const;
601 
602         /**
603          * Indicates whether or not the Managed Address Config Flag is set in the RA message header.
604          *
605          * @retval TRUE   The Managed Address Config Flag is set.
606          * @retval FALSE  The Managed Address Config Flag is not set.
607          *
608          */
IsManagedAddressConfigFlagSet(void) const609         bool IsManagedAddressConfigFlagSet(void) const { return (mFlags & kManagedAddressConfigFlag) != 0; }
610 
611         /**
612          * Sets the Managed Address Config Flag in the RA message.
613          *
614          */
SetManagedAddressConfigFlag(void)615         void SetManagedAddressConfigFlag(void) { mFlags |= kManagedAddressConfigFlag; }
616 
617         /**
618          * Indicates whether or not the Other Config Flag is set in the RA message header.
619          *
620          * @retval TRUE   The Other Config Flag is set.
621          * @retval FALSE  The Other Config Flag is not set.
622          *
623          */
IsOtherConfigFlagSet(void) const624         bool IsOtherConfigFlagSet(void) const { return (mFlags & kOtherConfigFlag) != 0; }
625 
626         /**
627          * Sets the Other Config Flag in the RA message.
628          *
629          */
SetOtherConfigFlag(void)630         void SetOtherConfigFlag(void) { mFlags |= kOtherConfigFlag; }
631 
632         /**
633          * This method returns the ICMPv6 message type.
634          *
635          * @returns The ICMPv6 message type.
636          *
637          */
GetType(void) const638         Icmp::Header::Type GetType(void) const { return static_cast<Icmp::Header::Type>(mType); }
639 
640     private:
641         // Router Advertisement Message
642         //
643         //   0                   1                   2                   3
644         //   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
645         //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
646         //  |     Type      |     Code      |          Checksum             |
647         //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
648         //  | Cur Hop Limit |M|O| |Prf|     |       Router Lifetime         |
649         //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
650         //  |                         Reachable Time                        |
651         //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
652         //  |                          Retrans Timer                        |
653         //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
654         //  |   Options ...
655         //  +-+-+-+-+-+-+-+-+-+-+-+-
656 
657         static constexpr uint8_t kManagedAddressConfigFlag = 1 << 7;
658         static constexpr uint8_t kOtherConfigFlag          = 1 << 6;
659         static constexpr uint8_t kPreferenceOffset         = 3;
660         static constexpr uint8_t kPreferenceMask           = 3 << kPreferenceOffset;
661 
662         uint8_t  mType;
663         uint8_t  mCode;
664         uint16_t mChecksum;
665         uint8_t  mCurHopLimit;
666         uint8_t  mFlags;
667         uint16_t mRouterLifetime;
668         uint32_t mReachableTime;
669         uint32_t mRetransTimer;
670     } OT_TOOL_PACKED_END;
671 
672     static_assert(sizeof(Header) == 16, "Invalid RA `Header`");
673 
674     typedef Data<kWithUint16Length> Icmp6Packet; ///< A data buffer containing an ICMPv6 packet.
675 
676     /**
677      * Represents a received RA message.
678      *
679      */
680     class RxMessage
681     {
682     public:
683         /**
684          * Initializes the RA message from a received packet data buffer.
685          *
686          * @param[in] aPacket   A received packet data.
687          *
688          */
RxMessage(const Icmp6Packet & aPacket)689         explicit RxMessage(const Icmp6Packet &aPacket)
690             : mData(aPacket)
691         {
692         }
693 
694         /**
695          * Gets the RA message as an `Icmp6Packet`.
696          *
697          * @returns The RA message as an `Icmp6Packet`.
698          *
699          */
GetAsPacket(void) const700         const Icmp6Packet &GetAsPacket(void) const { return mData; }
701 
702         /**
703          * Indicates whether or not the received RA message is valid.
704          *
705          * @retval TRUE   If the RA message is valid.
706          * @retval FALSE  If the RA message is not valid.
707          *
708          */
IsValid(void) const709         bool IsValid(void) const
710         {
711             return (mData.GetBytes() != nullptr) && (mData.GetLength() >= sizeof(Header)) &&
712                    (GetHeader().GetType() == Icmp::Header::kTypeRouterAdvert);
713         }
714 
715         /**
716          * Gets the RA message's header.
717          *
718          * @returns The RA message's header.
719          *
720          */
GetHeader(void) const721         const Header &GetHeader(void) const { return *reinterpret_cast<const Header *>(mData.GetBytes()); }
722 
723         /**
724          * Indicates whether or not the received RA message contains any options.
725          *
726          * @retval TRUE   If the RA message contains at least one option.
727          * @retval FALSE  If the RA message contains no options.
728          *
729          */
ContainsAnyOptions(void) const730         bool ContainsAnyOptions(void) const { return (mData.GetLength() > sizeof(Header)); }
731 
732         // The following methods are intended to support range-based `for`
733         // loop iteration over `Option`s in the RA message.
734 
begin(void) const735         Option::Iterator begin(void) const { return Option::Iterator(GetOptionStart(), GetDataEnd()); }
end(void) const736         Option::Iterator end(void) const { return Option::Iterator(); }
737 
738     private:
GetOptionStart(void) const739         const uint8_t *GetOptionStart(void) const { return (mData.GetBytes() + sizeof(Header)); }
GetDataEnd(void) const740         const uint8_t *GetDataEnd(void) const { return mData.GetBytes() + mData.GetLength(); }
741 
742         Data<kWithUint16Length> mData;
743     };
744 
745     /**
746      * Represents an RA message to be sent.
747      *
748      */
749     class TxMessage
750     {
751     public:
752         /**
753          * Gets the prepared RA message as an `Icmp6Packet`.
754          *
755          * @param[out] aPacket   A reference to an `Icmp6Packet`.
756          *
757          */
GetAsPacket(Icmp6Packet & aPacket) const758         void GetAsPacket(Icmp6Packet &aPacket) const { aPacket.Init(mArray.AsCArray(), mArray.GetLength()); }
759 
760         /**
761          * Appends the RA header.
762          *
763          * @param[in] aHeader  The RA header.
764          *
765          * @retval kErrorNone    Header is written successfully.
766          * @retval kErrorNoBufs  Insufficient available buffers to grow the message.
767          *
768          */
769         Error AppendHeader(const Header &aHeader);
770 
771         /**
772          * Appends a Prefix Info Option to the RA message.
773          *
774          * The appended Prefix Info Option will have both on-link (L) and autonomous address-configuration (A) flags
775          * set.
776          *
777          * @param[in] aPrefix             The prefix.
778          * @param[in] aValidLifetime      The valid lifetime in seconds.
779          * @param[in] aPreferredLifetime  The preferred lifetime in seconds.
780          *
781          * @retval kErrorNone    Option is appended successfully.
782          * @retval kErrorNoBufs  Insufficient available buffers to grow the message.
783          *
784          */
785         Error AppendPrefixInfoOption(const Prefix &aPrefix, uint32_t aValidLifetime, uint32_t aPreferredLifetime);
786 
787         /**
788          * Appends a Route Info Option to the RA message.
789          *
790          * @param[in] aPrefix             The prefix.
791          * @param[in] aRouteLifetime      The route lifetime in seconds.
792          * @param[in] aPreference         The route preference.
793          *
794          * @retval kErrorNone    Option is appended successfully.
795          * @retval kErrorNoBufs  Insufficient available buffers to grow the message.
796          *
797          */
798         Error AppendRouteInfoOption(const Prefix &aPrefix, uint32_t aRouteLifetime, RoutePreference aPreference);
799 
800         /**
801          * Appends a Flags Extension Option to the RA message.
802          *
803          * @param[in] aStubRouterFlag    The stub router flag.
804          *
805          * @retval kErrorNone    Option is appended successfully.
806          * @retval kErrorNoBufs  Insufficient available buffers to grow the message.
807          *
808          */
809         Error AppendFlagsExtensionOption(bool aStubRouterFlag);
810 
811         /**
812          * Appends bytes from a given buffer to the RA message.
813          *
814          * @param[in] aBytes     A pointer to the buffer containing the bytes to append.
815          * @param[in] aLength    The buffer length.
816          *
817          * @retval kErrorNone    Bytes are appended successfully.
818          * @retval kErrorNoBufs  Insufficient available buffers to grow the message.
819          *
820          */
821         Error AppendBytes(const uint8_t *aBytes, uint16_t aLength);
822 
823         /**
824          * Indicates whether or not the received RA message contains any options.
825          *
826          * @retval TRUE   If the RA message contains at least one option.
827          * @retval FALSE  If the RA message contains no options.
828          *
829          */
ContainsAnyOptions(void) const830         bool ContainsAnyOptions(void) const { return (mArray.GetLength() > sizeof(Header)); }
831 
832     private:
833         static constexpr uint16_t kCapacityIncrement = 256;
834 
835         Option *AppendOption(uint16_t aOptionSize);
836 
837         Heap::Array<uint8_t, kCapacityIncrement> mArray;
838     };
839 
840     RouterAdvert(void) = delete;
841 };
842 
843 /**
844  * Implements the Router Solicitation message.
845  *
846  * See section 4.1 of RFC 4861 for definition of this message.
847  * https://tools.ietf.org/html/rfc4861#section-4.1
848  *
849  */
850 OT_TOOL_PACKED_BEGIN
851 class RouterSolicitMessage
852 {
853 public:
854     /**
855      * Initializes the Router Solicitation message.
856      *
857      */
858     RouterSolicitMessage(void);
859 
860 private:
861     Icmp::Header mHeader; // The common ICMPv6 header.
862 } OT_TOOL_PACKED_END;
863 
864 static_assert(sizeof(RouterSolicitMessage) == 8, "invalid RouterSolicitMessage structure");
865 
866 /**
867  * Represents a Neighbor Solicitation (NS) message.
868  *
869  */
870 OT_TOOL_PACKED_BEGIN
871 class NeighborSolicitMessage : public Clearable<NeighborSolicitMessage>
872 {
873 public:
874     /**
875      * Initializes the Neighbor Solicitation message.
876      *
877      */
878     NeighborSolicitMessage(void);
879 
880     /**
881      * Indicates whether the Neighbor Solicitation message is valid (proper Type and Code).
882      *
883      * @retval TRUE  If the message is valid.
884      * @retval FALSE If the message is not valid.
885      *
886      */
IsValid(void) const887     bool IsValid(void) const { return (mType == Icmp::Header::kTypeNeighborSolicit) && (mCode == 0); }
888 
889     /**
890      * Gets the Target Address field.
891      *
892      * @returns The Target Address.
893      *
894      */
GetTargetAddress(void) const895     const Address &GetTargetAddress(void) const { return mTargetAddress; }
896 
897     /**
898      * Sets the Target Address field.
899      *
900      * @param[in] aTargetAddress  The Target Address.
901      *
902      */
SetTargetAddress(const Address & aTargetAddress)903     void SetTargetAddress(const Address &aTargetAddress) { mTargetAddress = aTargetAddress; }
904 
905 private:
906     // Neighbor Solicitation Message (RFC 4861)
907     //
908     //   0                   1                   2                   3
909     //   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
910     //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
911     //  |     Type      |     Code      |          Checksum             |
912     //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
913     //  |                           Reserved                            |
914     //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
915     //  |                                                               |
916     //  +                                                               +
917     //  |                                                               |
918     //  +                       Target Address                          +
919     //  |                                                               |
920     //  +                                                               +
921     //  |                                                               |
922     //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
923     //  |   Options ...
924     //  +-+-+-+-+-+-+-+-+-+-+-+-
925 
926     uint8_t  mType;
927     uint8_t  mCode;
928     uint16_t mChecksum;
929     uint32_t mReserved;
930     Address  mTargetAddress;
931 } OT_TOOL_PACKED_END;
932 
933 static_assert(sizeof(NeighborSolicitMessage) == 24, "Invalid NeighborSolicitMessage definition");
934 
935 /**
936  * Represents a Neighbor Advertisement (NA) message.
937  *
938  */
939 OT_TOOL_PACKED_BEGIN
940 class NeighborAdvertMessage : public Clearable<NeighborAdvertMessage>
941 {
942 public:
943     NeighborAdvertMessage(void);
944 
945     /**
946      * Indicates whether the Neighbor Advertisement message is valid (proper Type and Code).
947      *
948      * @retval TRUE  If the message is valid.
949      * @retval FALSE If the message is not valid.
950      *
951      */
IsValid(void) const952     bool IsValid(void) const { return (mType == Icmp::Header::kTypeNeighborAdvert) && (mCode == 0); }
953 
954     /**
955      * Indicates whether or not the Router Flag is set in the NA message.
956      *
957      * @retval TRUE   The Router Flag is set.
958      * @retval FALSE  The Router Flag is not set.
959      *
960      */
IsRouterFlagSet(void) const961     bool IsRouterFlagSet(void) const { return (mFlags & kRouterFlag) != 0; }
962 
963     /**
964      * Sets the Router Flag in the NA message.
965      *
966      */
SetRouterFlag(void)967     void SetRouterFlag(void) { mFlags |= kRouterFlag; }
968 
969     /**
970      * Indicates whether or not the Solicited Flag is set in the NA message.
971      *
972      * @retval TRUE   The Solicited Flag is set.
973      * @retval FALSE  The Solicited Flag is not set.
974      *
975      */
IsSolicitedFlagSet(void) const976     bool IsSolicitedFlagSet(void) const { return (mFlags & kSolicitedFlag) != 0; }
977 
978     /**
979      * Sets the Solicited Flag in the NA message.
980      *
981      */
SetSolicitedFlag(void)982     void SetSolicitedFlag(void) { mFlags |= kSolicitedFlag; }
983 
984     /**
985      * Indicates whether or not the Override Flag is set in the NA message.
986      *
987      * @retval TRUE   The Override Flag is set.
988      * @retval FALSE  The Override Flag is not set.
989      *
990      */
IsOverrideFlagSet(void) const991     bool IsOverrideFlagSet(void) const { return (mFlags & kOverrideFlag) != 0; }
992 
993     /**
994      * Sets the Override Flag in the NA message.
995      *
996      */
SetOverrideFlag(void)997     void SetOverrideFlag(void) { mFlags |= kOverrideFlag; }
998 
999     /**
1000      * Gets the Target Address field.
1001      *
1002      * @returns The Target Address.
1003      *
1004      */
GetTargetAddress(void) const1005     const Address &GetTargetAddress(void) const { return mTargetAddress; }
1006 
1007     /**
1008      * Sets the Target Address field.
1009      *
1010      * @param[in] aTargetAddress  The Target Address.
1011      *
1012      */
SetTargetAddress(const Address & aTargetAddress)1013     void SetTargetAddress(const Address &aTargetAddress) { mTargetAddress = aTargetAddress; }
1014 
1015 private:
1016     // Neighbor Advertisement Message (RFC 4861)
1017     //
1018     //   0                   1                   2                   3
1019     //   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
1020     //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1021     //  |     Type      |     Code      |          Checksum             |
1022     //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1023     //  |R|S|O|                     Reserved                            |
1024     //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1025     //  |                                                               |
1026     //  +                                                               +
1027     //  |                                                               |
1028     //  +                       Target Address                          +
1029     //  |                                                               |
1030     //  +                                                               +
1031     //  |                                                               |
1032     //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1033     //  |   Options ...
1034     //  +-+-+-+-+-+-+-+-+-+-+-+-
1035 
1036     static constexpr uint8_t kRouterFlag    = (1 << 7);
1037     static constexpr uint8_t kSolicitedFlag = (1 << 6);
1038     static constexpr uint8_t kOverrideFlag  = (1 << 5);
1039 
1040     uint8_t  mType;
1041     uint8_t  mCode;
1042     uint16_t mChecksum;
1043     uint8_t  mFlags;
1044     uint8_t  mReserved[3];
1045     Address  mTargetAddress;
1046 } OT_TOOL_PACKED_END;
1047 
1048 static_assert(sizeof(NeighborAdvertMessage) == 24, "Invalid NeighborAdvertMessage definition");
1049 
1050 } // namespace Nd
1051 } // namespace Ip6
1052 } // namespace ot
1053 
1054 #endif // ND6_HPP_
1055