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