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