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