1 /*
2  *  Copyright (c) 2016, 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 addresses.
32  */
33 
34 #ifndef IP6_ADDRESS_HPP_
35 #define IP6_ADDRESS_HPP_
36 
37 #include "openthread-core-config.h"
38 
39 #include <openthread/ip6.h>
40 
41 #include "common/as_core_type.hpp"
42 #include "common/clearable.hpp"
43 #include "common/encoding.hpp"
44 #include "common/equatable.hpp"
45 #include "common/num_utils.hpp"
46 #include "common/numeric_limits.hpp"
47 #include "common/string.hpp"
48 #include "mac/mac_types.hpp"
49 
50 namespace ot {
51 
52 namespace Ip4 {
53 // Forward declaration for SynthesizeFromIp4Address
54 class Address;
55 } // namespace Ip4
56 
57 namespace Ip6 {
58 
59 /**
60  * @addtogroup core-ip6-ip6
61  *
62  * @{
63  *
64  */
65 
66 /**
67  * Represents the Network Prefix of an IPv6 address (most significant 64 bits of the address).
68  *
69  */
70 OT_TOOL_PACKED_BEGIN
71 class NetworkPrefix : public otIp6NetworkPrefix, public Equatable<NetworkPrefix>, public Clearable<NetworkPrefix>
72 {
73 public:
74     static constexpr uint8_t kSize   = OT_IP6_PREFIX_SIZE;   ///< Size in bytes.
75     static constexpr uint8_t kLength = kSize * kBitsPerByte; ///< Length of Network Prefix in bits.
76 
77     /**
78      * Generates and sets the Network Prefix to a crypto-secure random Unique Local Address (ULA) based
79      * on the pattern `fdxx:xxxx:xxxx:` (RFC 4193).
80      *
81      * @retval kErrorNone     Successfully generated a random ULA Network Prefix
82      * @retval kErrorFailed   Failed to generate random ULA Network Prefix.
83      *
84      */
85     Error GenerateRandomUla(void);
86 
87 } OT_TOOL_PACKED_END;
88 
89 /**
90  * Represents an IPv6 Prefix.
91  *
92  */
93 OT_TOOL_PACKED_BEGIN
94 class Prefix : public otIp6Prefix, public Clearable<Prefix>, public Unequatable<Prefix>
95 {
96 public:
97     static constexpr uint8_t kMaxSize   = OT_IP6_ADDRESS_SIZE;     ///< Max (byte) size of a prefix.
98     static constexpr uint8_t kMaxLength = kMaxSize * kBitsPerByte; ///< Max length of a prefix in bits.
99 
100     static constexpr uint16_t kInfoStringSize = OT_IP6_PREFIX_STRING_SIZE; ///< Info string size (`ToString()`).
101 
102     /**
103      * Defines the fixed-length `String` object returned from `ToString()`.
104      *
105      */
106     typedef String<kInfoStringSize> InfoString;
107 
108     /**
109      * Gets the prefix as a pointer to a byte array.
110      *
111      * @returns A pointer to a byte array containing the Prefix.
112      *
113      */
GetBytes(void) const114     const uint8_t *GetBytes(void) const { return mPrefix.mFields.m8; }
115 
116     /**
117      * Gets the subnet ID of the prefix.
118      *
119      * @returns The 16-bit subnet ID.
120      *
121      */
GetSubnetId(void) const122     uint16_t GetSubnetId(void) const { return BigEndian::HostSwap16(mPrefix.mFields.m16[3]); }
123 
124     /**
125      * Gets the prefix length (in bits).
126      *
127      * @returns The prefix length (in bits).
128      *
129      */
GetLength(void) const130     uint8_t GetLength(void) const { return mLength; }
131 
132     /**
133      * Returns the size (in bytes) of the prefix.
134      *
135      * @returns The size (in bytes) of the prefix array.
136      *
137      */
GetBytesSize(void) const138     uint8_t GetBytesSize(void) const { return SizeForLength(mLength); }
139 
140     /**
141      * Sets the prefix.
142      *
143      * @param[in] aPrefix  A pointer to buffer containing the prefix bytes.
144      * @param[in] aLength  The length or prefix in bits.
145      *
146      */
147     void Set(const uint8_t *aPrefix, uint8_t aLength);
148 
149     /**
150      * Sets the prefix from a given Network Prefix.
151      *
152      * @param[in] aNetworkPrefix    A Network Prefix.
153      *
154      */
Set(const NetworkPrefix & aNetworkPrefix)155     void Set(const NetworkPrefix &aNetworkPrefix) { Set(aNetworkPrefix.m8, NetworkPrefix::kLength); }
156 
157     /**
158      * Sets the subnet ID of the prefix.
159      *
160      * @param[in] aSubnetId  A 16-bit subnet ID.
161      *
162      */
SetSubnetId(uint16_t aSubnetId)163     void SetSubnetId(uint16_t aSubnetId) { mPrefix.mFields.m16[3] = BigEndian::HostSwap16(aSubnetId); }
164 
165     /**
166      * Set the prefix length.
167      *
168      * @param[in] aLength  The new prefix length (in bits).
169      *
170      */
SetLength(uint8_t aLength)171     void SetLength(uint8_t aLength) { mLength = aLength; }
172 
173     /**
174      * Sets the bits after the prefix length to 0.
175      *
176      */
177     void Tidy(void);
178 
179     /**
180      * Indicates whether prefix length is valid (smaller or equal to max length).
181      *
182      * @retval TRUE   The prefix length is valid.
183      * @retval FALSE  The prefix length is not valid.
184      *
185      */
IsValid(void) const186     bool IsValid(void) const { return (mLength <= kMaxLength); }
187 
188     /**
189      * Indicates whether the prefix is a Link-Local prefix.
190      *
191      * @retval TRUE   The prefix is a Link-Local prefix.
192      * @retval FALSE  The prefix is not a Link-Local prefix.
193      *
194      */
195     bool IsLinkLocal(void) const;
196 
197     /**
198      * Indicates whether the prefix is a Multicast prefix.
199      *
200      * @retval TRUE   The prefix is a Multicast prefix.
201      * @retval FALSE  The prefix is not a Multicast prefix.
202      *
203      */
204     bool IsMulticast(void) const;
205 
206     /**
207      * Indicates whether the prefix is a Unique-Local prefix.
208      *
209      * @retval TRUE   The prefix is a Unique-Local prefix.
210      * @retval FALSE  The prefix is not a Unique-Local prefix.
211      *
212      */
213     bool IsUniqueLocal(void) const;
214 
215     /**
216      * Indicates whether the prefix is equal to a given prefix.
217      *
218      * @param[in] aPrefixBytes   A pointer to buffer containing the prefix bytes to compare with.
219      * @param[in] aPrefixLength  The length of prefix (in bits) specified by @p aPrefixBytes.
220      *
221      * @retval TRUE   If the prefix is equal to the specified prefix by @p aPrefixBytes and @p aPrefixLength.
222      * @retval FALSE  If the prefix is not equal to the specified prefix by @p aPrefixBytes and @p aPrefixLength.
223      *
224      */
225     bool IsEqual(const uint8_t *aPrefixBytes, uint8_t aPrefixLength) const;
226 
227     /**
228      * Indicates whether the prefix contains a sub-prefix.
229      *
230      * @param[in] aSubPrefix  A sub-prefix.
231      *
232      * @retval TRUE   The prefix contains the @p aSubPrefix
233      * @retval FALSE  The prefix does not contains the @p aSubPrefix.
234      *
235      */
236     bool ContainsPrefix(const Prefix &aSubPrefix) const;
237 
238     /**
239      * Indicates whether the prefix contains a sub-prefix (given as a `NetworkPrefix`).
240      *
241      * @param[in] aSubPrefix  A sub-prefix (as a `NetworkPrefix`).
242      *
243      * @retval TRUE   The prefix contains the @p aSubPrefix
244      * @retval FALSE  The prefix does not contains the @p aSubPrefix.
245      *
246      */
247     bool ContainsPrefix(const NetworkPrefix &aSubPrefix) const;
248 
249     /**
250      * Overloads operator `==` to evaluate whether or not two prefixes are equal.
251      *
252      * @param[in]  aOther  The other prefix to compare with.
253      *
254      * @retval TRUE   If the two prefixes are equal.
255      * @retval FALSE  If the two prefixes are not equal.
256      *
257      */
258     bool operator==(const Prefix &aOther) const;
259 
260     /**
261      * Overloads operator `<` to compare two prefixes.
262      *
263      * If the two prefixes have the same length N, then the bytes are compared directly (as two big-endian N-bit
264      * numbers). If the two prefix have different lengths, the shorter prefix is padded by `0` bit up to the longer
265      * prefix length N before the bytes are compared (as big-endian N-bit numbers). If all bytes are equal, the prefix
266      * with shorter length is considered smaller.
267      *
268      * @param[in] aOther  The other prefix to compare against.
269      *
270      * @retval TRUE   If the prefix is smaller than @p aOther.
271      * @retval FALSE  If the prefix is not smaller than @p aOther.
272      *
273      */
274     bool operator<(const Prefix &aOther) const;
275 
276     /**
277      * Converts a prefix length (in bits) to size (number of bytes).
278      *
279      * @param[in] aLength   A prefix length (in bits).
280      *
281      * @returns The size (in bytes) of the prefix.
282      *
283      */
SizeForLength(uint8_t aLength)284     static uint8_t SizeForLength(uint8_t aLength) { return BytesForBitSize(aLength); }
285 
286     /**
287      * Returns the number of IPv6 prefix bits that match.
288      *
289      * @param[in]  aPrefixA     A pointer to a byte array containing a first prefix.
290      * @param[in]  aPrefixB     A pointer to a byte array containing a second prefix.
291      * @param[in]  aMaxSize     Number of bytes of the two prefixes.
292      *
293      * @returns The number of prefix bits that match.
294      *
295      */
296     static uint8_t MatchLength(const uint8_t *aPrefixA, const uint8_t *aPrefixB, uint8_t aMaxSize);
297 
298     /**
299      * Indicates whether or not a given prefix length is valid for use as a NAT64 prefix.
300      *
301      * A NAT64 prefix must have one of the following lengths: 32, 40, 48, 56, 64, or 96 (per RFC 6052).
302      *
303      * @param[in] aLength The length of the prefix.
304      *
305      * @retval TRUE   If the prefix has a valid length for use as a NAT64 prefix.
306      * @retval FALSE  If the prefix does not have a valid length for use as a NAT64 prefix.
307      *
308      */
309     static bool IsValidNat64PrefixLength(uint8_t aLength);
310 
311     /**
312      * Indicates whether or not the prefix has a valid length for use as a NAT64 prefix.
313      *
314      * A NAT64 prefix must have one of the following lengths: 32, 40, 48, 56, 64, or 96 (per RFC 6052).
315      *
316      * @retval TRUE   If the prefix has a valid length for use as a NAT64 prefix.
317      * @retval FALSE  If the prefix does not have a valid length for use as a NAT64 prefix.
318      *
319      */
IsValidNat64(void) const320     bool IsValidNat64(void) const { return IsValidNat64PrefixLength(mLength); }
321 
322     /**
323      * Parses a given IPv6 prefix string and sets the prefix.
324      *
325      * @param[in]  aString         A null-terminated string, with format "<prefix>/<plen>"
326      *
327      * @retval kErrorNone          Successfully parsed the IPv6 prefix from @p aString.
328      * @retval kErrorParse         Failed to parse the IPv6 prefix from @p aString.
329      *
330      */
331     Error FromString(const char *aString);
332 
333     /**
334      * Converts the prefix to a string.
335      *
336      * The IPv6 prefix string is formatted as "%x:%x:%x:...[::]/plen".
337      *
338      * @returns An `InfoString` containing the string representation of the Prefix.
339      *
340      */
341     InfoString ToString(void) const;
342 
343     /**
344      * Converts the prefix to a string.
345      *
346      * The IPv6 prefix string is formatted as "%x:%x:%x:...[::]/plen".
347      *
348      * If the resulting string does not fit in @p aBuffer (within its @p aSize characters), the string will be
349      * truncated but the outputted string is always null-terminated.
350      *
351      * @param[out] aBuffer   A pointer to a char array to output the string (MUST NOT be `nullptr`).
352      * @param[in]  aSize     The size of @p aBuffer (in bytes).
353      *
354      */
355     void ToString(char *aBuffer, uint16_t aSize) const;
356 
357 private:
358     uint8_t ByteAfterTidy(uint8_t aIndex);
359     void    ToString(StringWriter &aWriter) const;
360 } OT_TOOL_PACKED_END;
361 
362 /**
363  * Represents the Interface Identifier of an IPv6 address.
364  *
365  */
366 OT_TOOL_PACKED_BEGIN
367 class InterfaceIdentifier : public otIp6InterfaceIdentifier,
368                             public Equatable<InterfaceIdentifier>,
369                             public Clearable<InterfaceIdentifier>
370 {
371     friend class Address;
372 
373 public:
374     static constexpr uint8_t kSize = OT_IP6_IID_SIZE; ///< Size of an IPv6 Interface Identifier (in bytes).
375 
376     static constexpr uint16_t kInfoStringSize = 17; ///< Max chars for the info string (`ToString()`).
377 
378     /**
379      * Defines the fixed-length `String` object returned from `ToString()`.
380      *
381      */
382     typedef String<kInfoStringSize> InfoString;
383 
384     /**
385      * Indicates whether or not the Interface Identifier is unspecified.
386      *
387      * @retval true  If the Interface Identifier is unspecified.
388      * @retval false If the Interface Identifier is not unspecified.
389      *
390      */
391     bool IsUnspecified(void) const;
392 
393     /**
394      * Indicates whether or not the Interface Identifier is reserved (RFC 5453).
395      *
396      * @retval true  If the Interface Identifier is reserved.
397      * @retval false If the Interface Identifier is not reserved.
398      *
399      */
400     bool IsReserved(void) const;
401 
402     /**
403      * Indicates whether or not the Interface Identifier is Subnet-Router Anycast (RFC 4291).
404      *
405      * @retval TRUE   If the Interface Identifier is a Subnet-Router Anycast address.
406      * @retval FALSE  If the Interface Identifier is not a Subnet-Router Anycast address.
407      *
408      */
409     bool IsSubnetRouterAnycast(void) const;
410 
411     /**
412      * Indicates whether or not the Interface Identifier is Reserved Subnet Anycast (RFC 2526).
413      *
414      * @retval TRUE   If the Interface Identifier is a Reserved Subnet Anycast address.
415      * @retval FALSE  If the Interface Identifier is not a Reserved Subnet Anycast address.
416      *
417      */
418     bool IsReservedSubnetAnycast(void) const;
419 
420     /**
421      * Generates and sets the Interface Identifier to a crypto-secure random byte sequence.
422      *
423      */
424     void GenerateRandom(void);
425 
426     /**
427      * Gets the Interface Identifier as a pointer to a byte array.
428      *
429      * @returns A pointer to a byte array (of size `kSize`) containing the Interface Identifier.
430      *
431      */
GetBytes(void) const432     const uint8_t *GetBytes(void) const { return mFields.m8; }
433 
434     /**
435      * Sets the Interface Identifier from a given byte array.
436      *
437      * @param[in] aBuffer    Pointer to an array containing the Interface Identifier. `kSize` bytes from the buffer
438      *                       are copied to form the Interface Identifier.
439      *
440      */
441     void SetBytes(const uint8_t *aBuffer);
442 
443     /**
444      * Sets the Interface Identifier from a given IEEE 802.15.4 Extended Address.
445      *
446      * @param[in] aExtAddress  An Extended Address.
447      *
448      */
449     void SetFromExtAddress(const Mac::ExtAddress &aExtAddress);
450 
451     /**
452      * Converts the Interface Identifier to an IEEE 802.15.4 Extended Address.
453      *
454      * @param[out]  aExtAddress  A reference to an Extended Address where the converted address is placed.
455      *
456      */
457     void ConvertToExtAddress(Mac::ExtAddress &aExtAddress) const;
458 
459     /**
460      * Converts the Interface Identifier to an IEEE 802.15.4 MAC Address.
461      *
462      * @param[out]  aMacAddress  A reference to a MAC Address where the converted address is placed.
463      *
464      */
465     void ConvertToMacAddress(Mac::Address &aMacAddress) const;
466 
467     /**
468      * Sets the Interface Identifier to Routing/Anycast Locator pattern `0000:00ff:fe00:xxxx` with a given
469      * locator (RLOC16 or ALOC16) value.
470      *
471      * @param[in]  aLocator    RLOC16 or ALOC16.
472      *
473      */
474     void SetToLocator(uint16_t aLocator);
475 
476     /**
477      * Indicates whether or not the Interface Identifier matches the locator pattern `0000:00ff:fe00:xxxx`.
478      *
479      * @retval TRUE   If the IID matches the locator pattern.
480      * @retval FALSE  If the IID does not match the locator pattern.
481      *
482      */
483     bool IsLocator(void) const;
484 
485     /**
486      * Indicates whether or not the Interface Identifier (IID) matches a Routing Locator (RLOC).
487      *
488      * In addition to checking that the IID matches the locator pattern (`0000:00ff:fe00:xxxx`), this method also
489      * checks that the locator value is a valid RLOC16.
490      *
491      * @retval TRUE   If the IID matches a RLOC address.
492      * @retval FALSE  If the IID does not match a RLOC address.
493      *
494      */
495     bool IsRoutingLocator(void) const;
496 
497     /**
498      * Indicates whether or not the Interface Identifier (IID) matches an Anycast Locator (ALOC).
499      *
500      * In addition to checking that the IID matches the locator pattern (`0000:00ff:fe00:xxxx`), this method also
501      * checks that the locator value is any valid ALOC16 (0xfc00 - 0xfcff).
502      *
503      * @retval TRUE   If the IID matches a ALOC address.
504      * @retval FALSE  If the IID does not match a ALOC address.
505      *
506      */
507     bool IsAnycastLocator(void) const;
508 
509     /**
510      * Indicates whether or not the Interface Identifier (IID) matches a Service Anycast Locator (ALOC).
511      *
512      * In addition to checking that the IID matches the locator pattern (`0000:00ff:fe00:xxxx`), this method also
513      * checks that the locator value is a valid Service ALOC16 (0xfc10 – 0xfc2f).
514      *
515      * @retval TRUE   If the IID matches a ALOC address.
516      * @retval FALSE  If the IID does not match a ALOC address.
517      *
518      */
519     bool IsAnycastServiceLocator(void) const;
520 
521     /**
522      * Gets the Interface Identifier (IID) address locator fields.
523      *
524      * Assumes the IID to match the locator pattern `0000:00ff:fe00:xxxx` (does not explicitly check this)
525      * and returns the last `uint16` portion of the IID.
526      *
527      * @returns The RLOC16 or ALOC16.
528      *
529      */
GetLocator(void) const530     uint16_t GetLocator(void) const { return BigEndian::HostSwap16(mFields.m16[3]); }
531 
532     /**
533      * Sets the Interface Identifier (IID) address locator field.
534      *
535      * Unlike `SetToLocator()`, this method only changes the last 2 bytes of the IID and keeps the rest of the address
536      * as before.
537      *
538      * @param[in]  aLocator   RLOC16 or ALOC16.
539      *
540      */
SetLocator(uint16_t aLocator)541     void SetLocator(uint16_t aLocator) { mFields.m16[3] = BigEndian::HostSwap16(aLocator); }
542 
543     /**
544      * Applies a prefix to IID.
545      *
546      * If the prefix length is longer than 64 bits, the prefix bits after 64 are written into the IID. This method only
547      * changes the bits in IID up the prefix length and keeps the rest of the bits in IID as before.
548      *
549      * @param[in] aPrefix   An IPv6 prefix.
550      *
551      */
552     void ApplyPrefix(const Prefix &aPrefix);
553 
554     /**
555      * Converts an Interface Identifier to a string.
556      *
557      * @returns An `InfoString` containing the string representation of the Interface Identifier.
558      *
559      */
560     InfoString ToString(void) const;
561 
562 private:
563     static constexpr uint8_t kAloc16Mask            = 0xfc; // The mask for ALOC16.
564     static constexpr uint8_t kRloc16ReservedBitMask = 0x02; // The mask for the reserved bit of RLOC16.
565 
566 } OT_TOOL_PACKED_END;
567 
568 /**
569  * Implements an IPv6 address object.
570  *
571  */
572 OT_TOOL_PACKED_BEGIN
573 class Address : public otIp6Address, public Equatable<Address>, public Clearable<Address>
574 {
575     friend class Prefix;
576     friend class InterfaceIdentifier;
577 
578 public:
579     static constexpr uint8_t kAloc16Mask = InterfaceIdentifier::kAloc16Mask; ///< The mask for ALOC16.
580 
581     static constexpr uint8_t kSize = OT_IP6_ADDRESS_SIZE; ///< Size of an IPv6 Address (in bytes).
582 
583     static constexpr uint16_t kInfoStringSize = OT_IP6_ADDRESS_STRING_SIZE; ///< String Size for IPv6 address.
584 
585     // IPv6 Address Scopes
586     static constexpr uint8_t kNodeLocalScope      = 0;  ///< Node-Local scope
587     static constexpr uint8_t kInterfaceLocalScope = 1;  ///< Interface-Local scope
588     static constexpr uint8_t kLinkLocalScope      = 2;  ///< Link-Local scope
589     static constexpr uint8_t kRealmLocalScope     = 3;  ///< Realm-Local scope
590     static constexpr uint8_t kAdminLocalScope     = 4;  ///< Admin-Local scope
591     static constexpr uint8_t kSiteLocalScope      = 5;  ///< Site-Local scope
592     static constexpr uint8_t kOrgLocalScope       = 8;  ///< Organization-Local scope
593     static constexpr uint8_t kGlobalScope         = 14; ///< Global scope
594 
595     /**
596      * Defines IPv6 address type filter.
597      *
598      */
599     enum TypeFilter : uint8_t
600     {
601         kTypeAny,                           ///< Accept any IPv6 address (unicast or multicast).
602         kTypeUnicast,                       ///< Accept unicast IPv6 addresses only.
603         kTypeMulticast,                     ///< Accept multicast IPv6 addresses only.
604         kTypeMulticastLargerThanRealmLocal, ///< Accept multicast IPv6 addresses with scope larger than Realm Local.
605     };
606 
607     /**
608      * Defines the fixed-length `String` object returned from `ToString()`.
609      *
610      */
611     typedef String<kInfoStringSize> InfoString;
612 
613     /**
614      * Gets the IPv6 address as a pointer to a byte array.
615      *
616      * @returns A pointer to a byte array containing the IPv6 address.
617      *
618      */
GetBytes(void) const619     const uint8_t *GetBytes(void) const { return mFields.m8; }
620 
621     /**
622      * Sets the IPv6 address from a given byte array.
623      *
624      * @param[in] aBuffer    Pointer to an array containing the IPv6 address. `kSize` bytes from the buffer
625      *                       are copied to form the IPv6 address.
626      *
627      */
SetBytes(const uint8_t * aBuffer)628     void SetBytes(const uint8_t *aBuffer) { memcpy(mFields.m8, aBuffer, kSize); }
629 
630     /**
631      * Indicates whether or not the IPv6 address is the Unspecified Address.
632      *
633      * @retval TRUE   If the IPv6 address is the Unspecified Address.
634      * @retval FALSE  If the IPv6 address is not the Unspecified Address.
635      *
636      */
637     bool IsUnspecified(void) const;
638 
639     /**
640      * Indicates whether or not the IPv6 address is the Loopback Address.
641      *
642      * @retval TRUE   If the IPv6 address is the Loopback Address.
643      * @retval FALSE  If the IPv6 address is not the Loopback Address.
644      *
645      */
646     bool IsLoopback(void) const;
647 
648     /**
649      * Indicates whether or not the IPv6 address scope is Link-Local.
650      *
651      * @retval TRUE   If the IPv6 address scope is Link-Local.
652      * @retval FALSE  If the IPv6 address scope is not Link-Local.
653      *
654      */
655     bool IsLinkLocal(void) const;
656 
657     /**
658      * Sets the IPv6 address to a Link-Local address with Interface Identifier generated from a given
659      * MAC Extended Address.
660      *
661      * @param[in]  aExtAddress  A MAC Extended Address (used to generate the IID).
662      *
663      */
664     void SetToLinkLocalAddress(const Mac::ExtAddress &aExtAddress);
665 
666     /**
667      * Sets the IPv6 address to a Link-Local address with a given Interface Identifier.
668      *
669      * @param[in]  aIid   An Interface Identifier.
670      *
671      */
672     void SetToLinkLocalAddress(const InterfaceIdentifier &aIid);
673 
674     /**
675      * Indicates whether or not the IPv6 address is multicast address.
676      *
677      * @retval TRUE   If the IPv6 address is a multicast address.
678      * @retval FALSE  If the IPv6 address scope is not a multicast address.
679      *
680      */
IsMulticast(void) const681     bool IsMulticast(void) const { return mFields.m8[0] == 0xff; }
682 
683     /**
684      * Indicates whether or not the IPv6 address is a link-local multicast address.
685      *
686      * @retval TRUE   If the IPv6 address is a link-local multicast address.
687      * @retval FALSE  If the IPv6 address scope is not a link-local multicast address.
688      *
689      */
690     bool IsLinkLocalMulticast(void) const;
691 
692     /**
693      * Indicates whether or not the IPv6 address is a link-local all nodes multicast address (ff02::01).
694      *
695      * @retval TRUE   If the IPv6 address is a link-local all nodes multicast address.
696      * @retval FALSE  If the IPv6 address is not a link-local all nodes multicast address.
697      *
698      */
699     bool IsLinkLocalAllNodesMulticast(void) const;
700 
701     /**
702      * Sets the IPv6 address to the link-local all nodes multicast address (ff02::01).
703      *
704      */
705     void SetToLinkLocalAllNodesMulticast(void);
706 
707     /**
708      * Indicates whether or not the IPv6 address is a link-local all routers multicast address (ff02::02).
709      *
710      * @retval TRUE   If the IPv6 address is a link-local all routers multicast address.
711      * @retval FALSE  If the IPv6 address is not a link-local all routers multicast address.
712      *
713      */
714     bool IsLinkLocalAllRoutersMulticast(void) const;
715 
716     /**
717      * Sets the IPv6 address to the link-local all routers multicast address (ff02::02).
718      *
719      */
720     void SetToLinkLocalAllRoutersMulticast(void);
721 
722     /**
723      * Indicates whether or not the IPv6 address is a realm-local multicast address.
724      *
725      * @retval TRUE   If the IPv6 address is a realm-local multicast address.
726      * @retval FALSE  If the IPv6 address scope is not a realm-local multicast address.
727      *
728      */
729     bool IsRealmLocalMulticast(void) const;
730 
731     /**
732      * Indicates whether or not the IPv6 address is a realm-local all nodes multicast address (ff03::01).
733      *
734      * @retval TRUE   If the IPv6 address is a realm-local all nodes multicast address.
735      * @retval FALSE  If the IPv6 address is not a realm-local all nodes multicast address.
736      *
737      */
738     bool IsRealmLocalAllNodesMulticast(void) const;
739 
740     /**
741      * Sets the IPv6 address to the realm-local all nodes multicast address (ff03::01)
742      *
743      */
744     void SetToRealmLocalAllNodesMulticast(void);
745 
746     /**
747      * Indicates whether or not the IPv6 address is a realm-local all routers multicast address (ff03::02).
748      *
749      * @retval TRUE   If the IPv6 address is a realm-local all routers multicast address.
750      * @retval FALSE  If the IPv6 address is not a realm-local all routers multicast address.
751      *
752      */
753     bool IsRealmLocalAllRoutersMulticast(void) const;
754 
755     /**
756      * Sets the IPv6 address to the realm-local all routers multicast address (ff03::02).
757      *
758      */
759     void SetToRealmLocalAllRoutersMulticast(void);
760 
761     /**
762      * Indicates whether or not the IPv6 address is a realm-local all MPL forwarders address (ff03::fc).
763      *
764      * @retval TRUE   If the IPv6 address is a realm-local all MPL forwarders address.
765      * @retval FALSE  If the IPv6 address is not a realm-local all MPL forwarders address.
766      *
767      */
768     bool IsRealmLocalAllMplForwarders(void) const;
769 
770     /**
771      * Sets the the IPv6 address to the realm-local all MPL forwarders address (ff03::fc).
772      *
773      */
774     void SetToRealmLocalAllMplForwarders(void);
775 
776     /**
777      * Indicates whether or not the IPv6 address is multicast larger than realm local.
778      *
779      * @retval TRUE   If the IPv6 address is multicast larger than realm local.
780      * @retval FALSE  If the IPv6 address is not multicast or the scope is not larger than realm local.
781      *
782      */
783     bool IsMulticastLargerThanRealmLocal(void) const;
784 
785     /**
786      * Sets the IPv6 address to a Routing Locator (RLOC) IPv6 address with a given Network Prefix and
787      * RLOC16 value.
788      *
789      * @param[in]  aNetworkPrefix    A Network Prefix.
790      * @param[in]  aRloc16           A RLOC16 value.
791      *
792      */
SetToRoutingLocator(const NetworkPrefix & aNetworkPrefix,uint16_t aRloc16)793     void SetToRoutingLocator(const NetworkPrefix &aNetworkPrefix, uint16_t aRloc16)
794     {
795         SetToLocator(aNetworkPrefix, aRloc16);
796     }
797 
798     /**
799      * Sets the IPv6 address to a Anycast Locator (ALOC) IPv6 address with a given Network Prefix and
800      * ALOC16 value.
801      *
802      * @param[in]  aNetworkPrefix    A Network Prefix.
803      * @param[in]  aAloc16           A ALOC16 value.
804      *
805      */
SetToAnycastLocator(const NetworkPrefix & aNetworkPrefix,uint16_t aAloc16)806     void SetToAnycastLocator(const NetworkPrefix &aNetworkPrefix, uint16_t aAloc16)
807     {
808         SetToLocator(aNetworkPrefix, aAloc16);
809     }
810 
811     /**
812      * Indicates whether or not the IPv6 address follows the IPv4-mapped format.
813      *
814      * An IPv4-mapped IPv6 address consists of an 80-bit prefix of zeros, the next 16 bits set to  ones, and the
815      * remaining, least-significant 32 bits contain the IPv4 address, e.g., `::ffff:192.0.2.128` representing
816      * `192.0.2.128` IPv4 address.
817      *
818      * @retval TRUE   If the IPv6 address follows the IPv4-mapped format.
819      * @retval FALSE  If the IPv6 address does not follow the IPv4-mapped format.
820      *
821      */
822     bool IsIp4Mapped(void) const;
823 
824     /**
825      * Sets the IPv6 address to follow the IPv4-mapped IPv6 address for a given IPv4 address.
826      *
827      * @param[in] aIp4Address  An IPv4 address.
828      *
829      */
830     void SetToIp4Mapped(const Ip4::Address &aIp4Address);
831 
832     /**
833      * Returns the Network Prefix of the IPv6 address (most significant 64 bits of the address).
834      *
835      * @returns A reference to the Network Prefix.
836      *
837      */
GetPrefix(void) const838     const NetworkPrefix &GetPrefix(void) const
839     {
840         return static_cast<const NetworkPrefix &>(mFields.mComponents.mNetworkPrefix);
841     }
842 
843     /**
844      * Gets a prefix of the IPv6 address with a given length.
845      *
846      * @param[in]  aLength  The length of prefix in bits.
847      * @param[out] aPrefix  A reference to a prefix to output the fetched prefix.
848      *
849      */
GetPrefix(uint8_t aLength,Prefix & aPrefix) const850     void GetPrefix(uint8_t aLength, Prefix &aPrefix) const { aPrefix.Set(mFields.m8, aLength); }
851 
852     /**
853      * Indicates whether the IPv6 address matches a given prefix.
854      *
855      * @param[in] aPrefix  An IPv6 prefix to match with.
856      *
857      * @retval TRUE   The IPv6 address matches the @p aPrefix.
858      * @retval FALSE  The IPv6 address does not match the @p aPrefix.
859      *
860      */
861     bool MatchesPrefix(const Prefix &aPrefix) const;
862 
863     /**
864      * Indicates whether the IPv6 address matches a given prefix.
865      *
866      * @param[in]  aPrefix         A buffer containing the prefix.
867      * @param[in]  aPrefixLength   The prefix length (in bits).
868      *
869      * @retval TRUE   The IPv6 address matches the @p aPrefix.
870      * @retval FALSE  The IPv6 address does not match the @p aPrefix.
871      *
872      */
873     bool MatchesPrefix(const uint8_t *aPrefix, uint8_t aPrefixLength) const;
874 
875     /**
876      * Sets the IPv6 address prefix.
877      *
878      * Only changes the first @p aPrefixLength bits of the address and keeps the rest of the bits in the
879      * address as before.
880      *
881      * @param[in]  aPrefix         A buffer containing the prefix.
882      * @param[in]  aPrefixLength   The prefix length (in bits).
883      *
884      */
SetPrefix(const uint8_t * aPrefix,uint8_t aPrefixLength)885     void SetPrefix(const uint8_t *aPrefix, uint8_t aPrefixLength) { CopyBits(mFields.m8, aPrefix, aPrefixLength); }
886 
887     /**
888      * Sets the IPv6 address prefix to the given Network Prefix.
889      *
890      * @param[in]  aNetworkPrefix   A Network Prefix.
891      *
892      */
893     void SetPrefix(const NetworkPrefix &aNetworkPrefix);
894 
895     /**
896      * Sets the IPv6 address prefix.
897      *
898      * Only changes the initial prefix length bits of the IPv6 address and keeps the rest of the bits in
899      * the address as before.
900      *
901      * @param[in]  aPrefix         An IPv6 prefix.
902      *
903      */
904     void SetPrefix(const Prefix &aPrefix);
905 
906     /**
907      * Sets the prefix content of the Prefix-Based Multicast Address.
908      *
909      * @param[in]  aPrefix         A buffer containing the prefix.
910      * @param[in]  aPrefixLength   The prefix length (in bits).
911      *
912      */
913     void SetMulticastNetworkPrefix(const uint8_t *aPrefix, uint8_t aPrefixLength);
914 
915     /**
916      * Sets the prefix content of Prefix-Based Multicast Address.
917      *
918      * @param[in]  aNetworkPrefix   A reference to a Network Prefix.
919      *
920      */
SetMulticastNetworkPrefix(const NetworkPrefix & aNetworkPrefix)921     void SetMulticastNetworkPrefix(const NetworkPrefix &aNetworkPrefix)
922     {
923         SetMulticastNetworkPrefix(aNetworkPrefix.m8, NetworkPrefix::kLength);
924     }
925 
926     /**
927      * Sets the prefix content of Prefix-Based Multicast Address.
928      *
929      * @param[in]  aPrefix  An IPv6 Prefix.
930      *
931      */
SetMulticastNetworkPrefix(const Prefix & aPrefix)932     void SetMulticastNetworkPrefix(const Prefix &aPrefix)
933     {
934         SetMulticastNetworkPrefix(aPrefix.GetBytes(), aPrefix.GetLength());
935     }
936 
937     /**
938      * Returns the Interface Identifier of the IPv6 address.
939      *
940      * @returns A reference to the Interface Identifier.
941      *
942      */
GetIid(void) const943     const InterfaceIdentifier &GetIid(void) const
944     {
945         return static_cast<const InterfaceIdentifier &>(mFields.mComponents.mIid);
946     }
947 
948     /**
949      * Returns the Interface Identifier of the IPv6 address.
950      *
951      * @returns A reference to the Interface Identifier.
952      *
953      */
GetIid(void)954     InterfaceIdentifier &GetIid(void) { return static_cast<InterfaceIdentifier &>(mFields.mComponents.mIid); }
955 
956     /**
957      * Sets the Interface Identifier.
958      *
959      * @param[in]  aIid  An Interface Identifier.
960      *
961      */
SetIid(const InterfaceIdentifier & aIid)962     void SetIid(const InterfaceIdentifier &aIid) { GetIid() = aIid; }
963 
964     /**
965      * Returns the IPv6 address scope.
966      *
967      * @returns The IPv6 address scope.
968      *
969      */
970     uint8_t GetScope(void) const;
971 
972     /**
973      * Returns the number of IPv6 prefix bits that match.
974      *
975      * @param[in]  aOther  The IPv6 address to match against.
976      *
977      * @returns The number of IPv6 prefix bits that match.
978      *
979      */
980     uint8_t PrefixMatch(const Address &aOther) const;
981 
982     /**
983      * Indicates whether address matches a given type filter.
984      *
985      * @param[in] aFilter   An address type filter.
986      *
987      * @retval TRUE   The address matches @p aFilter.
988      * @retval FALSE  The address does not match @p aFilter.
989      *
990      */
991     bool MatchesFilter(TypeFilter aFilter) const;
992 
993     /**
994      * Sets the IPv6 address by performing NAT64 address translation from a given IPv4 address as specified
995      * in RFC 6052.
996      *
997      * The NAT64 @p aPrefix MUST have one of the following lengths: 32, 40, 48, 56, 64, or 96, otherwise the behavior
998      * of this method is undefined.
999      *
1000      * @param[in] aPrefix      The prefix to use for IPv4/IPv6 translation.
1001      * @param[in] aIp4Address  The IPv4 address to translate to IPv6.
1002      *
1003      */
1004     void SynthesizeFromIp4Address(const Prefix &aPrefix, const Ip4::Address &aIp4Address);
1005 
1006     /**
1007      * Converts an IPv6 address string to binary.
1008      *
1009      * @param[in]  aString  A pointer to the null-terminated string.
1010      *
1011      * @retval kErrorNone          Successfully parsed the IPv6 address string.
1012      * @retval kErrorParse         Failed to parse the IPv6 address string.
1013      *
1014      */
1015     Error FromString(const char *aString);
1016 
1017     /**
1018      * Converts the IPv6 address to a string.
1019      *
1020      * The IPv6 address string is formatted as 16 hex values separated by ':' (i.e., "%x:%x:%x:...:%x").
1021      *
1022      * @returns An `InfoString` representing the IPv6 address.
1023      *
1024      */
1025     InfoString ToString(void) const;
1026 
1027     /**
1028      * Convert the IPv6 address to a C string.
1029      *
1030      * The IPv6 address string is formatted as 16 hex values separated by ':' (i.e., "%x:%x:%x:...:%x").
1031      *
1032      * If the resulting string does not fit in @p aBuffer (within its @p aSize characters), the string will be
1033      * truncated but the outputted string is always null-terminated.
1034      *
1035      * @param[out] aBuffer   A pointer to a char array to output the string (MUST NOT be `nullptr`).
1036      * @param[in]  aSize     The size of @p aBuffer (in bytes).
1037      *
1038      */
1039     void ToString(char *aBuffer, uint16_t aSize) const;
1040 
1041     /**
1042      * Overloads operator `<` to compare two IPv6 addresses.
1043      *
1044      * @param[in] aOther  The other IPv6 address to compare with.
1045      *
1046      * @retval true   The IPv6 address is smaller than @p aOther.
1047      * @retval false  The IPv6 address is larger than or equal to @p aOther.
1048      *
1049      */
operator <(const Address & aOther) const1050     bool operator<(const Address &aOther) const { return memcmp(mFields.m8, aOther.mFields.m8, sizeof(Address)) < 0; }
1051 
1052 private:
1053     static constexpr uint8_t kMulticastNetworkPrefixLengthOffset = 3; // Prefix-Based Multicast Address (RFC3306)
1054     static constexpr uint8_t kMulticastNetworkPrefixOffset       = 4; // Prefix-Based Multicast Address (RFC3306)
1055 
1056     void SetToLocator(const NetworkPrefix &aNetworkPrefix, uint16_t aLocator);
1057     void ToString(StringWriter &aWriter) const;
1058     void AppendHexWords(StringWriter &aWriter, uint8_t aLength) const;
1059 
1060     static const Address &GetLinkLocalAllNodesMulticast(void);
1061     static const Address &GetLinkLocalAllRoutersMulticast(void);
1062     static const Address &GetRealmLocalAllNodesMulticast(void);
1063     static const Address &GetRealmLocalAllRoutersMulticast(void);
1064     static const Address &GetRealmLocalAllMplForwarders(void);
1065 
1066     static void CopyBits(uint8_t *aDst, const uint8_t *aSrc, uint8_t aNumBits);
1067 
1068     Error ParseFrom(const char *aString, char aTerminatorChar);
1069 
1070 } OT_TOOL_PACKED_END;
1071 
1072 /**
1073  * @}
1074  *
1075  */
1076 
1077 } // namespace Ip6
1078 
1079 DefineCoreType(otIp6NetworkPrefix, Ip6::NetworkPrefix);
1080 DefineCoreType(otIp6Prefix, Ip6::Prefix);
1081 DefineCoreType(otIp6InterfaceIdentifier, Ip6::InterfaceIdentifier);
1082 DefineCoreType(otIp6Address, Ip6::Address);
1083 
1084 } // namespace ot
1085 
1086 #endif // IP6_ADDRESS_HPP_
1087