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  * This function 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  * This class 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      * This constructor 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      * This method 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      * Sets the prefix of NAT64-mapped addresses in the thread network. The address mapping table will not be cleared.
256      * This function equals to `ClearNat64Prefix` when an empty prefix is provided.
257      *
258      * @param[in] aNat64Prefix The prefix of the NAT64-mapped addresses.
259      *
260      */
261     void SetNat64Prefix(const Ip6::Prefix &aNat64Prefix);
262 
263     /**
264      * Clear the prefix of NAT64-mapped addresses in the thread network. The address mapping table will not be cleared.
265      * The translator will return kNotTranslated for all IPv6 datagrams and kDrop for all IPv4 datagrams.
266      *
267      */
268     void ClearNat64Prefix(void);
269 
270     /**
271      * Initializes an `otNat64AddressMappingIterator`.
272      *
273      * An iterator MUST be initialized before it is used.
274      *
275      * An iterator can be initialized again to restart from the beginning of the mapping info.
276      *
277      * @param[out] aIterator  An iterator to initialize.
278      *
279      */
280     void InitAddressMappingIterator(AddressMappingIterator &aIterator);
281 
282     /**
283      * Gets the next AddressMapping info (using an iterator).
284      *
285      * @param[in,out]  aIterator      The iterator. On success the iterator will be updated to point to next NAT64
286      *                                address mapping record. To get the first entry the iterator should be set to
287      *                                OT_NAT64_ADDRESS_MAPPING_ITERATOR_INIT.
288      * @param[out]     aMapping       An `otNat64AddressMapping` where information of next NAT64 address mapping record
289      *                                is placed (on success).
290      *
291      * @retval kErrorNone      Successfully found the next NAT64 address mapping info (@p aMapping was successfully
292      *                         updated).
293      * @retval kErrorNotFound  No subsequent NAT64 address mapping info was found.
294      *
295      */
296     Error GetNextAddressMapping(AddressMappingIterator &aIterator, otNat64AddressMapping &aMapping);
297 
298     /**
299      * Gets the NAT64 translator counters.
300      *
301      * The counters are initialized to zero when the OpenThread instance is initialized.
302      *
303      * @param[out] aCounters A `ProtocolCounters` where the counters of NAT64 translator will be placed.
304      *
305      */
GetCounters(ProtocolCounters & aCounters) const306     void GetCounters(ProtocolCounters &aCounters) const { aCounters = mCounters; }
307 
308     /**
309      * Gets the NAT64 translator error counters.
310      *
311      * The counters are initialized to zero when the OpenThread instance is initialized.
312      *
313      * @param[out] aCounters  An `ErrorCounters` where the counters of NAT64 translator will be placed.
314      *
315      */
GetErrorCounters(ErrorCounters & aCounters) const316     void GetErrorCounters(ErrorCounters &aCounters) const { aCounters = mErrorCounters; }
317 
318     /**
319      * Gets the configured CIDR in the NAT64 translator.
320      *
321      * @param[out] aCidr        The `Ip4::Cidr` Where the configured CIDR will be placed.
322      *
323      * @retval kErrorNone       @p aCidr is set to the configured CIDR.
324      * @retval kErrorNotFound   The translator is not configured with an IPv4 CIDR.
325      *
326      */
327     Error GetIp4Cidr(Ip4::Cidr &aCidr);
328 
329     /**
330      * Gets the configured IPv6 prefix in the NAT64 translator.
331      *
332      * @param[out] aPrefix      The `Ip6::Prefix` where the configured NAT64 prefix will be placed.
333      *
334      * @retval kErrorNone       @p aPrefix is set to the configured prefix.
335      * @retval kErrorNotFound   The translator is not configured with an IPv6 prefix.
336      *
337      */
338     Error GetIp6Prefix(Ip6::Prefix &aPrefix);
339 
340 private:
341     class AddressMapping : public LinkedListEntry<AddressMapping>
342     {
343     public:
344         friend class LinkedListEntry<AddressMapping>;
345         friend class LinkedList<AddressMapping>;
346 
347         typedef String<Ip6::Address::kInfoStringSize + Ip4::Address::kAddressStringSize + 4> InfoString;
348 
Touch(TimeMilli aNow)349         void       Touch(TimeMilli aNow) { mExpiry = aNow + kAddressMappingIdleTimeoutMsec; }
350         InfoString ToString(void) const;
351         void       CopyTo(otNat64AddressMapping &aMapping, TimeMilli aNow) const;
352 
353         uint64_t mId; // The unique id for a mapping session.
354 
355         Ip4::Address mIp4;
356         Ip6::Address mIp6;
357         TimeMilli    mExpiry; // The timestamp when this mapping expires, in milliseconds.
358 
359         ProtocolCounters mCounters;
360 
361     private:
Matches(const Ip4::Address & aIp4) const362         bool Matches(const Ip4::Address &aIp4) const { return mIp4 == aIp4; }
Matches(const Ip6::Address & aIp6) const363         bool Matches(const Ip6::Address &aIp6) const { return mIp6 == aIp6; }
Matches(const TimeMilli aNow) const364         bool Matches(const TimeMilli aNow) const { return mExpiry < aNow; }
365 
366         AddressMapping *mNext;
367     };
368 
369     Error TranslateIcmp4(Message &aMessage);
370     Error TranslateIcmp6(Message &aMessage);
371 
372     uint16_t        ReleaseMappings(LinkedList<AddressMapping> &aMappings);
373     void            ReleaseMapping(AddressMapping &aMapping);
374     uint16_t        ReleaseExpiredMappings(void);
375     AddressMapping *AllocateMapping(const Ip6::Address &aIp6Addr);
376     AddressMapping *FindOrAllocateMapping(const Ip6::Address &aIp6Addr);
377     AddressMapping *FindMapping(const Ip4::Address &aIp4Addr);
378 
379     void HandleMappingExpirerTimer(void);
380 
381     using MappingTimer = TimerMilliIn<Translator, &Translator::HandleMappingExpirerTimer>;
382 
383     void UpdateState(void);
384 
385     bool  mEnabled;
386     State mState;
387 
388     uint64_t mNextMappingId;
389 
390     Array<Ip4::Address, kAddressMappingPoolSize>  mIp4AddressPool;
391     Pool<AddressMapping, kAddressMappingPoolSize> mAddressMappingPool;
392     LinkedList<AddressMapping>                    mActiveAddressMappings;
393 
394     Ip6::Prefix mNat64Prefix;
395     Ip4::Cidr   mIp4Cidr;
396 
397     MappingTimer mMappingExpirerTimer;
398 
399     ProtocolCounters mCounters;
400     ErrorCounters    mErrorCounters;
401 };
402 #endif // OPENTHREAD_CONFIG_NAT64_TRANSLATOR_ENABLE
403 
404 } // namespace Nat64
405 
406 DefineMapEnum(otNat64State, Nat64::State);
407 #if OPENTHREAD_CONFIG_NAT64_TRANSLATOR_ENABLE
408 DefineCoreType(otNat64ProtocolCounters, Nat64::Translator::ProtocolCounters);
409 DefineCoreType(otNat64ErrorCounters, Nat64::Translator::ErrorCounters);
410 #endif
411 
412 } // namespace ot
413 
414 #endif // NAT64_TRANSLATOR_HPP_
415