xref: /aosp_15_r20/external/openthread/src/core/net/nat64_translator.hpp (revision cfb92d1480a9e65faed56933e9c12405f45898b4)
1 /*
2  *  Copyright (c) 2022, 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 the NAT64 translator.
32  *
33  */
34 
35 #ifndef NAT64_TRANSLATOR_HPP_
36 #define NAT64_TRANSLATOR_HPP_
37 
38 #include "openthread-core-config.h"
39 
40 #include "common/array.hpp"
41 #include "common/linked_list.hpp"
42 #include "common/locator.hpp"
43 #include "common/pool.hpp"
44 #include "common/timer.hpp"
45 #include "net/ip4_types.hpp"
46 #include "net/ip6.hpp"
47 
48 namespace ot {
49 namespace Nat64 {
50 
51 enum State : uint8_t
52 {
53     kStateDisabled   = OT_NAT64_STATE_DISABLED,    ///< The component is disabled.
54     kStateNotRunning = OT_NAT64_STATE_NOT_RUNNING, ///< The component is enabled, but is not running.
55     kStateIdle       = OT_NAT64_STATE_IDLE,        ///< NAT64 is enabled, but this BR is not an active NAT64 BR.
56     kStateActive     = OT_NAT64_STATE_ACTIVE,      ///< The component is running.
57 };
58 
59 /**
60  * Converts a `State` into a string.
61  *
62  * @param[in]  aState     A state.
63  *
64  * @returns  A string representation of @p aState.
65  *
66  */
67 const char *StateToString(State aState);
68 
69 #if OPENTHREAD_CONFIG_NAT64_TRANSLATOR_ENABLE
70 
71 /**
72  * Implements the NAT64 translator.
73  *
74  */
75 class Translator : public InstanceLocator, private NonCopyable
76 {
77 public:
78     static constexpr uint32_t kAddressMappingIdleTimeoutMsec =
79         OPENTHREAD_CONFIG_NAT64_IDLE_TIMEOUT_SECONDS * Time::kOneSecondInMsec;
80     static constexpr uint32_t kAddressMappingPoolSize = OPENTHREAD_CONFIG_NAT64_MAX_MAPPINGS;
81 
82     typedef otNat64AddressMappingIterator AddressMappingIterator; ///< Address mapping Iterator.
83 
84     /**
85      * The possible results of NAT64 translation.
86      *
87      */
88     enum Result : uint8_t
89     {
90         kNotTranslated, ///< The message is not translated, it might be sending to an non-nat64 prefix (for outgoing
91                         ///< datagrams), or it is already an IPv6 message (for incoming datagrams).
92         kForward,       ///< Message is successfully translated, the caller should continue forwarding the translated
93                         ///< datagram.
94         kDrop,          ///< The caller should drop the datagram silently.
95     };
96 
97     /**
98      * Represents the counters for the protocols supported by NAT64.
99      *
100      */
101     class ProtocolCounters : public otNat64ProtocolCounters, public Clearable<ProtocolCounters>
102     {
103     public:
104         /**
105          * Adds the packet to the counter for the given IPv6 protocol.
106          *
107          * @param[in] aProtocol    The protocol of the packet.
108          * @param[in] aPacketSize  The size of the packet.
109          *
110          */
111         void Count6To4Packet(uint8_t aProtocol, uint64_t aPacketSize);
112 
113         /**
114          * Adds the packet to the counter for the given IPv4 protocol.
115          *
116          * @param[in] aProtocol    The protocol of the packet.
117          * @param[in] aPacketSize  The size of the packet.
118          *
119          */
120         void Count4To6Packet(uint8_t aProtocol, uint64_t aPacketSize);
121     };
122 
123     /**
124      * Represents the counters of dropped packets due to errors when handling NAT64 packets.
125      *
126      */
127     class ErrorCounters : public otNat64ErrorCounters, public Clearable<otNat64ErrorCounters>
128     {
129     public:
130         enum Reason : uint8_t
131         {
132             kUnknown          = OT_NAT64_DROP_REASON_UNKNOWN,
133             kIllegalPacket    = OT_NAT64_DROP_REASON_ILLEGAL_PACKET,
134             kUnsupportedProto = OT_NAT64_DROP_REASON_UNSUPPORTED_PROTO,
135             kNoMapping        = OT_NAT64_DROP_REASON_NO_MAPPING,
136         };
137 
138         /**
139          * Adds the counter for the given reason when translating an IPv4 datagram.
140          *
141          * @param[in] aReason    The reason of packet drop.
142          *
143          */
Count4To6(Reason aReason)144         void Count4To6(Reason aReason) { mCount4To6[aReason]++; }
145 
146         /**
147          * Adds the counter for the given reason when translating an IPv6 datagram.
148          *
149          * @param[in] aReason    The reason of packet drop.
150          *
151          */
Count6To4(Reason aReason)152         void Count6To4(Reason aReason) { mCount6To4[aReason]++; }
153     };
154 
155     /**
156      * Initializes the NAT64 translator.
157      *
158      */
159     explicit Translator(Instance &aInstance);
160 
161     /**
162      * Set the state of NAT64 translator.
163      *
164      * Note: Disabling the translator will invalidate all address mappings.
165      *
166      * @param[in]  aEnabled   A boolean to enable/disable NAT64 translator.
167      *
168      */
169     void SetEnabled(bool aEnabled);
170 
171     /**
172      * Gets the state of NAT64 translator.
173      *
174      * @retval  kNat64StateDisabled  The translator is disabled.
175      * @retval  kNat64StateIdle      The translator is not configured with a valid NAT64 prefix and a CIDR.
176      * @retval  kNat64StateActive    The translator is translating packets.
177      *
178      */
GetState(void) const179     State GetState(void) const { return mState; }
180 
181     /**
182      * Translates an IPv4 datagram to an IPv6 datagram and sends it via Thread interface.
183      *
184      * The caller transfers ownership of @p aMessage when making this call. OpenThread will free @p aMessage when
185      * processing is complete, including when a value other than `kErrorNone` is returned.
186      *
187      * @param[in]  aMessage          A reference to the message.
188      *
189      * @retval kErrorNone     Successfully processed the message.
190      * @retval kErrorDrop     Message was well-formed but not fully processed due to datagram processing rules.
191      * @retval kErrorNoBufs   Could not allocate necessary message buffers when processing the datagram.
192      * @retval kErrorNoRoute  No route to host.
193      * @retval kErrorParse    Encountered a malformed header when processing the message.
194      *
195      */
196     Error SendMessage(Message &aMessage);
197 
198     /**
199      * Allocate a new message buffer for sending an IPv4 message (which will be translated into an IPv6 datagram by
200      * NAT64 later). Message buffers allocated by this function will have 20 bytes (The differences between the size of
201      * IPv6 headers and the size of IPv4 headers) reserved.
202      *
203      * @param[in]  aSettings  The message settings.
204      *
205      * @returns A pointer to the message buffer or NULL if no message buffers are available or parameters are invalid.
206      *
207      */
208     Message *NewIp4Message(const Message::Settings &aSettings);
209 
210     /**
211      * Translates an IPv4 datagram to IPv6 datagram. Note the datagram and datagramLength might be adjusted.
212      * Note the message can have 20 bytes reserved before the message to avoid potential copy operations. If the message
213      * is already an IPv6 datagram, `Result::kNotTranslated` will be returned and @p aMessage won't be modified.
214      *
215      * @param[in,out] aMessage the message to be processed.
216      *
217      * @retval kNotTranslated The message is already an IPv6 datagram. @p aMessage is not updated.
218      * @retval kForward       The caller should continue forwarding the datagram.
219      * @retval kDrop          The caller should drop the datagram silently.
220      *
221      */
222     Result TranslateToIp6(Message &message);
223 
224     /**
225      * Translates an IPv6 datagram to IPv4 datagram. Note the datagram and datagramLength might be adjusted.
226      * If the message is not targeted to NAT64-mapped address, `Result::kNotTranslated` will be returned and @p aMessage
227      * won't be modified.
228      *
229      * @param[in,out] aMessage the message to be processed.
230      *
231      * @retval kNotTranslated The datagram is not sending to the configured NAT64 prefix.
232      * @retval kForward       The caller should continue forwarding the datagram.
233      * @retval kDrop          The caller should drop the datagram silently.
234      *
235      */
236     Result TranslateFromIp6(Message &aMessage);
237 
238     /**
239      * Sets the CIDR used when setting the source address of the outgoing translated IPv4 datagrams. A valid CIDR must
240      * have a non-zero prefix length.
241      *
242      * @note The actual addresses pool is limited by the size of the mapping pool and the number of addresses available
243      * in the CIDR block. If the provided is a valid IPv4 CIDR for NAT64, and it is different from the one already
244      * configured, the NAT64 translator will be reset and all existing sessions will be expired.
245      *
246      * @param[in] aCidr the CIDR for the sources of the translated datagrams.
247      *
248      * @retval  kErrorInvalidArgs    The the given CIDR a valid CIDR for NAT64.
249      * @retval  kErrorNone           Successfully enabled/disabled the NAT64 translator.
250      *
251      */
252     Error SetIp4Cidr(const Ip4::Cidr &aCidr);
253 
254     /**
255      * Clears the CIDR used when setting the source address of the outgoing translated IPv4 datagrams.
256      *
257      * @note The NAT64 translator will be reset and all existing sessions will be expired when clearing the configured
258      * CIDR.
259      */
260     void ClearIp4Cidr(void);
261 
262     /**
263      * Sets the prefix of NAT64-mapped addresses in the thread network. The address mapping table will not be cleared.
264      * Equals to `ClearNat64Prefix` when an empty prefix is provided.
265      *
266      * @param[in] aNat64Prefix The prefix of the NAT64-mapped addresses.
267      *
268      */
269     void SetNat64Prefix(const Ip6::Prefix &aNat64Prefix);
270 
271     /**
272      * Clear the prefix of NAT64-mapped addresses in the thread network. The address mapping table will not be cleared.
273      * The translator will return kNotTranslated for all IPv6 datagrams and kDrop for all IPv4 datagrams.
274      *
275      */
276     void ClearNat64Prefix(void);
277 
278     /**
279      * Initializes an `otNat64AddressMappingIterator`.
280      *
281      * An iterator MUST be initialized before it is used.
282      *
283      * An iterator can be initialized again to restart from the beginning of the mapping info.
284      *
285      * @param[out] aIterator  An iterator to initialize.
286      *
287      */
288     void InitAddressMappingIterator(AddressMappingIterator &aIterator);
289 
290     /**
291      * Gets the next AddressMapping info (using an iterator).
292      *
293      * @param[in,out]  aIterator      The iterator. On success the iterator will be updated to point to next NAT64
294      *                                address mapping record. To get the first entry the iterator should be set to
295      *                                OT_NAT64_ADDRESS_MAPPING_ITERATOR_INIT.
296      * @param[out]     aMapping       An `otNat64AddressMapping` where information of next NAT64 address mapping record
297      *                                is placed (on success).
298      *
299      * @retval kErrorNone      Successfully found the next NAT64 address mapping info (@p aMapping was successfully
300      *                         updated).
301      * @retval kErrorNotFound  No subsequent NAT64 address mapping info was found.
302      *
303      */
304     Error GetNextAddressMapping(AddressMappingIterator &aIterator, otNat64AddressMapping &aMapping);
305 
306     /**
307      * Gets the NAT64 translator counters.
308      *
309      * The counters are initialized to zero when the OpenThread instance is initialized.
310      *
311      * @param[out] aCounters A `ProtocolCounters` where the counters of NAT64 translator will be placed.
312      *
313      */
GetCounters(ProtocolCounters & aCounters) const314     void GetCounters(ProtocolCounters &aCounters) const { aCounters = mCounters; }
315 
316     /**
317      * Gets the NAT64 translator error counters.
318      *
319      * The counters are initialized to zero when the OpenThread instance is initialized.
320      *
321      * @param[out] aCounters  An `ErrorCounters` where the counters of NAT64 translator will be placed.
322      *
323      */
GetErrorCounters(ErrorCounters & aCounters) const324     void GetErrorCounters(ErrorCounters &aCounters) const { aCounters = mErrorCounters; }
325 
326     /**
327      * Gets the configured CIDR in the NAT64 translator.
328      *
329      * @param[out] aCidr        The `Ip4::Cidr` Where the configured CIDR will be placed.
330      *
331      * @retval kErrorNone       @p aCidr is set to the configured CIDR.
332      * @retval kErrorNotFound   The translator is not configured with an IPv4 CIDR.
333      *
334      */
335     Error GetIp4Cidr(Ip4::Cidr &aCidr);
336 
337     /**
338      * Gets the configured IPv6 prefix in the NAT64 translator.
339      *
340      * @param[out] aPrefix      The `Ip6::Prefix` where the configured NAT64 prefix will be placed.
341      *
342      * @retval kErrorNone       @p aPrefix is set to the configured prefix.
343      * @retval kErrorNotFound   The translator is not configured with an IPv6 prefix.
344      *
345      */
346     Error GetIp6Prefix(Ip6::Prefix &aPrefix);
347 
348 private:
349     class AddressMapping : public LinkedListEntry<AddressMapping>
350     {
351     public:
352         friend class LinkedListEntry<AddressMapping>;
353         friend class LinkedList<AddressMapping>;
354 
355         typedef String<Ip6::Address::kInfoStringSize + Ip4::Address::kAddressStringSize + 4> InfoString;
356 
Touch(TimeMilli aNow)357         void       Touch(TimeMilli aNow) { mExpiry = aNow + kAddressMappingIdleTimeoutMsec; }
358         InfoString ToString(void) const;
359         void       CopyTo(otNat64AddressMapping &aMapping, TimeMilli aNow) const;
360 
361         uint64_t mId; // The unique id for a mapping session.
362 
363         Ip4::Address mIp4;
364         Ip6::Address mIp6;
365         TimeMilli    mExpiry; // The timestamp when this mapping expires, in milliseconds.
366 
367         ProtocolCounters mCounters;
368 
369     private:
Matches(const Ip4::Address & aIp4) const370         bool Matches(const Ip4::Address &aIp4) const { return mIp4 == aIp4; }
Matches(const Ip6::Address & aIp6) const371         bool Matches(const Ip6::Address &aIp6) const { return mIp6 == aIp6; }
Matches(const TimeMilli aNow) const372         bool Matches(const TimeMilli aNow) const { return mExpiry < aNow; }
373 
374         AddressMapping *mNext;
375     };
376 
377     Error TranslateIcmp4(Message &aMessage);
378     Error TranslateIcmp6(Message &aMessage);
379 
380     uint16_t        ReleaseMappings(LinkedList<AddressMapping> &aMappings);
381     void            ReleaseMapping(AddressMapping &aMapping);
382     uint16_t        ReleaseExpiredMappings(void);
383     AddressMapping *AllocateMapping(const Ip6::Address &aIp6Addr);
384     AddressMapping *FindOrAllocateMapping(const Ip6::Address &aIp6Addr);
385     AddressMapping *FindMapping(const Ip4::Address &aIp4Addr);
386 
387     void HandleMappingExpirerTimer(void);
388 
389     using MappingTimer = TimerMilliIn<Translator, &Translator::HandleMappingExpirerTimer>;
390 
391     void UpdateState(void);
392 
393     bool  mEnabled;
394     State mState;
395 
396     uint64_t mNextMappingId;
397 
398     Array<Ip4::Address, kAddressMappingPoolSize>  mIp4AddressPool;
399     Pool<AddressMapping, kAddressMappingPoolSize> mAddressMappingPool;
400     LinkedList<AddressMapping>                    mActiveAddressMappings;
401 
402     Ip6::Prefix mNat64Prefix;
403     Ip4::Cidr   mIp4Cidr;
404 
405     MappingTimer mMappingExpirerTimer;
406 
407     ProtocolCounters mCounters;
408     ErrorCounters    mErrorCounters;
409 };
410 #endif // OPENTHREAD_CONFIG_NAT64_TRANSLATOR_ENABLE
411 
412 } // namespace Nat64
413 
414 DefineMapEnum(otNat64State, Nat64::State);
415 #if OPENTHREAD_CONFIG_NAT64_TRANSLATOR_ENABLE
416 DefineCoreType(otNat64ProtocolCounters, Nat64::Translator::ProtocolCounters);
417 DefineCoreType(otNat64ErrorCounters, Nat64::Translator::ErrorCounters);
418 #endif
419 
420 } // namespace ot
421 
422 #endif // NAT64_TRANSLATOR_HPP_
423