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