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  * @brief
32  *  This file defines the OpenThread API for NAT64 on a border router.
33  */
34 
35 #ifndef OPENTHREAD_NAT64_H_
36 #define OPENTHREAD_NAT64_H_
37 
38 #include <openthread/ip6.h>
39 #include <openthread/message.h>
40 
41 #ifdef __cplusplus
42 extern "C" {
43 #endif
44 
45 /**
46  * @addtogroup api-nat64
47  *
48  * @brief This module includes functions and structs for the NAT64 function on the border router. These functions are
49  * only available when `OPENTHREAD_CONFIG_NAT64_BORDER_ROUTING_ENABLE` is enabled.
50  *
51  * @{
52  *
53  */
54 
55 #define OT_IP4_ADDRESS_SIZE 4 ///< Size of an IPv4 address (bytes)
56 
57 /**
58  * @struct otIp4Address
59  *
60  * Represents an IPv4 address.
61  *
62  */
63 OT_TOOL_PACKED_BEGIN
64 struct otIp4Address
65 {
66     union OT_TOOL_PACKED_FIELD
67     {
68         uint8_t  m8[OT_IP4_ADDRESS_SIZE]; ///< 8-bit fields
69         uint32_t m32;                     ///< 32-bit representation
70     } mFields;
71 } OT_TOOL_PACKED_END;
72 
73 /**
74  * Represents an IPv4 address.
75  *
76  */
77 typedef struct otIp4Address otIp4Address;
78 
79 /**
80  * @struct otIp4Cidr
81  *
82  * Represents an IPv4 CIDR block.
83  *
84  */
85 typedef struct otIp4Cidr
86 {
87     otIp4Address mAddress;
88     uint8_t      mLength;
89 } otIp4Cidr;
90 
91 /**
92  * Represents the counters for NAT64.
93  *
94  */
95 typedef struct otNat64Counters
96 {
97     uint64_t m4To6Packets; ///< Number of packets translated from IPv4 to IPv6.
98     uint64_t m4To6Bytes;   ///< Sum of size of packets translated from IPv4 to IPv6.
99     uint64_t m6To4Packets; ///< Number of packets translated from IPv6 to IPv4.
100     uint64_t m6To4Bytes;   ///< Sum of size of packets translated from IPv6 to IPv4.
101 } otNat64Counters;
102 
103 /**
104  * Represents the counters for the protocols supported by NAT64.
105  *
106  */
107 typedef struct otNat64ProtocolCounters
108 {
109     otNat64Counters mTotal; ///< Counters for sum of all protocols.
110     otNat64Counters mIcmp;  ///< Counters for ICMP and ICMPv6.
111     otNat64Counters mUdp;   ///< Counters for UDP.
112     otNat64Counters mTcp;   ///< Counters for TCP.
113 } otNat64ProtocolCounters;
114 
115 /**
116  * Packet drop reasons.
117  *
118  */
119 typedef enum otNat64DropReason
120 {
121     OT_NAT64_DROP_REASON_UNKNOWN = 0,       ///< Packet drop for unknown reasons.
122     OT_NAT64_DROP_REASON_ILLEGAL_PACKET,    ///< Packet drop due to failed to parse the datagram.
123     OT_NAT64_DROP_REASON_UNSUPPORTED_PROTO, ///< Packet drop due to unsupported IP protocol.
124     OT_NAT64_DROP_REASON_NO_MAPPING,        ///< Packet drop due to no mappings found or mapping pool exhausted.
125     //---
126     OT_NAT64_DROP_REASON_COUNT,
127 } otNat64DropReason;
128 
129 /**
130  * Represents the counters of dropped packets due to errors when handling NAT64 packets.
131  *
132  */
133 typedef struct otNat64ErrorCounters
134 {
135     uint64_t mCount4To6[OT_NAT64_DROP_REASON_COUNT]; ///< Errors translating IPv4 packets.
136     uint64_t mCount6To4[OT_NAT64_DROP_REASON_COUNT]; ///< Errors translating IPv6 packets.
137 } otNat64ErrorCounters;
138 
139 /**
140  * Gets NAT64 translator counters.
141  *
142  * The counter is counted since the instance initialized.
143  *
144  * Available when `OPENTHREAD_CONFIG_NAT64_TRANSLATOR_ENABLE` is enabled.
145  *
146  * @param[in]  aInstance A pointer to an OpenThread instance.
147  * @param[out] aCounters A pointer to an `otNat64Counters` where the counters of NAT64 translator will be placed.
148  *
149  */
150 void otNat64GetCounters(otInstance *aInstance, otNat64ProtocolCounters *aCounters);
151 
152 /**
153  * Gets the NAT64 translator error counters.
154  *
155  * The counters are initialized to zero when the OpenThread instance is initialized.
156  *
157  * @param[in]  aInstance A pointer to an OpenThread instance.
158  * @param[out] aCounters A pointer to an `otNat64Counters` where the counters of NAT64 translator will be placed.
159  *
160  */
161 void otNat64GetErrorCounters(otInstance *aInstance, otNat64ErrorCounters *aCounters);
162 
163 /**
164  * Represents an address mapping record for NAT64.
165  *
166  * @note The counters will be reset for each mapping session even for the same address pair. Applications can use `mId`
167  * to identify different sessions to calculate the packets correctly.
168  *
169  */
170 typedef struct otNat64AddressMapping
171 {
172     uint64_t mId; ///< The unique id for a mapping session.
173 
174     otIp4Address mIp4;             ///< The IPv4 address of the mapping.
175     otIp6Address mIp6;             ///< The IPv6 address of the mapping.
176     uint32_t     mRemainingTimeMs; ///< Remaining time before expiry in milliseconds.
177 
178     otNat64ProtocolCounters mCounters;
179 } otNat64AddressMapping;
180 
181 /**
182  * Used to iterate through NAT64 address mappings.
183  *
184  * The fields in this type are opaque (intended for use by OpenThread core only) and therefore should not be
185  * accessed or used by caller.
186  *
187  * Before using an iterator, it MUST be initialized using `otNat64AddressMappingIteratorInit()`.
188  *
189  */
190 typedef struct otNat64AddressMappingIterator
191 {
192     void *mPtr;
193 } otNat64AddressMappingIterator;
194 
195 /**
196  * Initializes an `otNat64AddressMappingIterator`.
197  *
198  * An iterator MUST be initialized before it is used.
199  *
200  * An iterator can be initialized again to restart from the beginning of the mapping info.
201  *
202  * @param[in]  aInstance  The OpenThread instance.
203  * @param[out] aIterator  A pointer to the iterator to initialize.
204  *
205  */
206 void otNat64InitAddressMappingIterator(otInstance *aInstance, otNat64AddressMappingIterator *aIterator);
207 
208 /**
209  * Gets the next AddressMapping info (using an iterator).
210  *
211  * Available when `OPENTHREAD_CONFIG_NAT64_TRANSLATOR_ENABLE` is enabled.
212  *
213  * @param[in]      aInstance      A pointer to an OpenThread instance.
214  * @param[in,out]  aIterator      A pointer to the iterator. On success the iterator will be updated to point to next
215  *                                NAT64 address mapping record. To get the first entry the iterator should be set to
216  *                                OT_NAT64_ADDRESS_MAPPING_ITERATOR_INIT.
217  * @param[out]     aMapping       A pointer to an `otNat64AddressMapping` where information of next NAT64 address
218  *                                mapping record is placed (on success).
219  *
220  * @retval OT_ERROR_NONE       Successfully found the next NAT64 address mapping info (@p aMapping was successfully
221  *                             updated).
222  * @retval OT_ERROR_NOT_FOUND  No subsequent NAT64 address mapping info was found.
223  *
224  */
225 otError otNat64GetNextAddressMapping(otInstance                    *aInstance,
226                                      otNat64AddressMappingIterator *aIterator,
227                                      otNat64AddressMapping         *aMapping);
228 
229 /**
230  * States of NAT64.
231  *
232  */
233 typedef enum
234 {
235     OT_NAT64_STATE_DISABLED = 0, ///< NAT64 is disabled.
236     OT_NAT64_STATE_NOT_RUNNING,  ///< NAT64 is enabled, but one or more dependencies of NAT64 are not running.
237     OT_NAT64_STATE_IDLE,         ///< NAT64 is enabled, but this BR is not an active NAT64 BR.
238     OT_NAT64_STATE_ACTIVE,       ///< The BR is publishing a NAT64 prefix and/or translating packets.
239 } otNat64State;
240 
241 /**
242  * Gets the state of NAT64 translator.
243  *
244  * Available when `OPENTHREAD_CONFIG_NAT64_TRANSLATOR_ENABLE` is enabled.
245  *
246  * @param[in]  aInstance          A pointer to an OpenThread instance.
247  *
248  * @retval OT_NAT64_STATE_DISABLED    NAT64 translator is disabled.
249  * @retval OT_NAT64_STATE_NOT_RUNNING NAT64 translator is enabled, but the translator is not configured with a valid
250  *                                    NAT64 prefix and a CIDR.
251  * @retval OT_NAT64_STATE_ACTIVE      NAT64 translator is enabled, and is translating packets.
252  *
253  */
254 otNat64State otNat64GetTranslatorState(otInstance *aInstance);
255 
256 /**
257  * Gets the state of NAT64 prefix manager.
258  *
259  * Available when `OPENTHREAD_CONFIG_NAT64_BORDER_ROUTING_ENABLE` is enabled.
260  *
261  * @param[in]  aInstance          A pointer to an OpenThread instance.
262  *
263  * @retval OT_NAT64_STATE_DISABLED    NAT64 prefix manager is disabled.
264  * @retval OT_NAT64_STATE_NOT_RUNNING NAT64 prefix manager is enabled, but is not running (because the routing manager
265  *                                    is not running).
266  * @retval OT_NAT64_STATE_IDLE        NAT64 prefix manager is enabled, but is not publishing a NAT64 prefix. Usually
267  *                                    when there is another border router publishing a NAT64 prefix with higher
268  *                                    priority.
269  * @retval OT_NAT64_STATE_ACTIVE      NAT64 prefix manager is enabled, and is publishing NAT64 prefix to the Thread
270  *                                    network.
271  *
272  */
273 otNat64State otNat64GetPrefixManagerState(otInstance *aInstance);
274 
275 /**
276  * Enable or disable NAT64 functions.
277  *
278  * Note: This includes the NAT64 Translator (when `OPENTHREAD_CONFIG_NAT64_TRANSLATOR_ENABLE` is enabled) and the NAT64
279  * Prefix Manager (when `OPENTHREAD_CONFIG_NAT64_BORDER_ROUTING_ENABLE` is enabled).
280  *
281  * When `OPENTHREAD_CONFIG_NAT64_TRANSLATOR_ENABLE` is enabled, setting disabled to true resets the
282  * mapping table in the translator.
283  *
284  * Available when `OPENTHREAD_CONFIG_NAT64_TRANSLATOR_ENABLE` or `OPENTHREAD_CONFIG_NAT64_BORDER_ROUTING_ENABLE` is
285  * enabled.
286  *
287  * @param[in]  aInstance  A pointer to an OpenThread instance.
288  * @param[in]  aEnabled   A boolean to enable/disable the NAT64 functions
289  *
290  * @sa otNat64GetTranslatorState
291  * @sa otNat64GetPrefixManagerState
292  *
293  */
294 void otNat64SetEnabled(otInstance *aInstance, bool aEnabled);
295 
296 /**
297  * Allocate a new message buffer for sending an IPv4 message to the NAT64 translator.
298  *
299  * Message buffers allocated by this function will have 20 bytes (difference between the size of IPv6 headers
300  * and IPv4 header sizes) reserved.
301  *
302  * Available when `OPENTHREAD_CONFIG_NAT64_TRANSLATOR_ENABLE` is enabled.
303  *
304  * @note If @p aSettings is `NULL`, the link layer security is enabled and the message priority is set to
305  * OT_MESSAGE_PRIORITY_NORMAL by default.
306  *
307  * @param[in]  aInstance  A pointer to an OpenThread instance.
308  * @param[in]  aSettings  A pointer to the message settings or NULL to set default settings.
309  *
310  * @returns A pointer to the message buffer or NULL if no message buffers are available or parameters are invalid.
311  *
312  * @sa otNat64Send
313  *
314  */
315 otMessage *otIp4NewMessage(otInstance *aInstance, const otMessageSettings *aSettings);
316 
317 /**
318  * Sets the CIDR used when setting the source address of the outgoing translated IPv4 packets.
319  *
320  * Is available only when OPENTHREAD_CONFIG_NAT64_TRANSLATOR_ENABLE is enabled.
321  *
322  * @note A valid CIDR must have a non-zero prefix length. The actual addresses pool is limited by the size of the
323  * mapping pool and the number of addresses available in the CIDR block.
324  *
325  * @note This function can be called at any time, but the NAT64 translator will be reset and all existing sessions will
326  * be expired when updating the configured CIDR.
327  *
328  * @param[in] aInstance  A pointer to an OpenThread instance.
329  * @param[in] aCidr      A pointer to an otIp4Cidr for the IPv4 CIDR block for NAT64.
330  *
331  * @retval  OT_ERROR_INVALID_ARGS   The given CIDR is not a valid IPv4 CIDR for NAT64.
332  * @retval  OT_ERROR_NONE           Successfully set the CIDR for NAT64.
333  *
334  * @sa otBorderRouterSend
335  * @sa otBorderRouterSetReceiveCallback
336  *
337  */
338 otError otNat64SetIp4Cidr(otInstance *aInstance, const otIp4Cidr *aCidr);
339 
340 /**
341  * Translates an IPv4 datagram to an IPv6 datagram and sends via the Thread interface.
342  *
343  * The caller transfers ownership of @p aMessage when making this call. OpenThread will free @p aMessage when
344  * processing is complete, including when a value other than `OT_ERROR_NONE` is returned.
345  *
346  * @param[in]  aInstance A pointer to an OpenThread instance.
347  * @param[in]  aMessage  A pointer to the message buffer containing the IPv4 datagram.
348  *
349  * @retval OT_ERROR_NONE                    Successfully processed the message.
350  * @retval OT_ERROR_DROP                    Message was well-formed but not fully processed due to packet processing
351  *                                          rules.
352  * @retval OT_ERROR_NO_BUFS                 Could not allocate necessary message buffers when processing the datagram.
353  * @retval OT_ERROR_NO_ROUTE                No route to host.
354  * @retval OT_ERROR_INVALID_SOURCE_ADDRESS  Source address is invalid, e.g. an anycast address or a multicast address.
355  * @retval OT_ERROR_PARSE                   Encountered a malformed header when processing the message.
356  *
357  */
358 otError otNat64Send(otInstance *aInstance, otMessage *aMessage);
359 
360 /**
361  * Pointer is called when an IPv4 datagram (translated by NAT64 translator) is received.
362  *
363  * @param[in]  aMessage  A pointer to the message buffer containing the received IPv6 datagram. This function transfers
364  *                       the ownership of the @p aMessage to the receiver of the callback. The message should be
365  *                       freed by the receiver of the callback after it is processed.
366  * @param[in]  aContext  A pointer to application-specific context.
367  *
368  */
369 typedef void (*otNat64ReceiveIp4Callback)(otMessage *aMessage, void *aContext);
370 
371 /**
372  * Registers a callback to provide received IPv4 datagrams.
373  *
374  * @param[in]  aInstance         A pointer to an OpenThread instance.
375  * @param[in]  aCallback         A pointer to a function that is called when an IPv4 datagram is received or
376  *                               NULL to disable the callback.
377  * @param[in]  aContext          A pointer to application-specific context.
378  *
379  */
380 void otNat64SetReceiveIp4Callback(otInstance *aInstance, otNat64ReceiveIp4Callback aCallback, void *aContext);
381 
382 /**
383  * Gets the IPv4 CIDR configured in the NAT64 translator.
384  *
385  * Available when `OPENTHREAD_CONFIG_NAT64_TRANSLATOR_ENABLE` is enabled.
386  *
387  * @param[in]  aInstance         A pointer to an OpenThread instance.
388  * @param[out] aCidr             A pointer to an otIp4Cidr. Where the CIDR will be filled.
389  *
390  */
391 otError otNat64GetCidr(otInstance *aInstance, otIp4Cidr *aCidr);
392 
393 /**
394  * Test if two IPv4 addresses are the same.
395  *
396  * @param[in]  aFirst   A pointer to the first IPv4 address to compare.
397  * @param[in]  aSecond  A pointer to the second IPv4 address to compare.
398  *
399  * @retval TRUE   The two IPv4 addresses are the same.
400  * @retval FALSE  The two IPv4 addresses are not the same.
401  *
402  */
403 bool otIp4IsAddressEqual(const otIp4Address *aFirst, const otIp4Address *aSecond);
404 
405 /**
406  * Set @p aIp4Address by performing NAT64 address translation from @p aIp6Address as specified
407  * in RFC 6052.
408  *
409  * The NAT64 @p aPrefixLength MUST be one of the following values: 32, 40, 48, 56, 64, or 96, otherwise the behavior
410  * of this method is undefined.
411  *
412  * @param[in]  aPrefixLength  The prefix length to use for IPv4/IPv6 translation.
413  * @param[in]  aIp6Address    A pointer to an IPv6 address.
414  * @param[out] aIp4Address    A pointer to output the IPv4 address.
415  *
416  */
417 void otIp4ExtractFromIp6Address(uint8_t aPrefixLength, const otIp6Address *aIp6Address, otIp4Address *aIp4Address);
418 
419 #define OT_IP4_ADDRESS_STRING_SIZE 17 ///< Length of 000.000.000.000 plus a suffix NUL
420 
421 /**
422  * Converts the address to a string.
423  *
424  * The string format uses quad-dotted notation of four bytes in the address (e.g., "127.0.0.1").
425  *
426  * If the resulting string does not fit in @p aBuffer (within its @p aSize characters), the string will be
427  * truncated but the outputted string is always null-terminated.
428  *
429  * @param[in]  aAddress  A pointer to an IPv4 address (MUST NOT be NULL).
430  * @param[out] aBuffer   A pointer to a char array to output the string (MUST NOT be `nullptr`).
431  * @param[in]  aSize     The size of @p aBuffer (in bytes).
432  *
433  */
434 void otIp4AddressToString(const otIp4Address *aAddress, char *aBuffer, uint16_t aSize);
435 
436 #define OT_IP4_CIDR_STRING_SIZE 20 ///< Length of 000.000.000.000/00 plus a suffix NUL
437 
438 /**
439  * Converts a human-readable IPv4 CIDR string into a binary representation.
440  *
441  * @param[in]   aString   A pointer to a NULL-terminated string.
442  * @param[out]  aCidr     A pointer to an IPv4 CIDR.
443  *
444  * @retval OT_ERROR_NONE          Successfully parsed the string.
445  * @retval OT_ERROR_INVALID_ARGS  Failed to parse the string.
446  *
447  */
448 otError otIp4CidrFromString(const char *aString, otIp4Cidr *aCidr);
449 
450 /**
451  * Converts the IPv4 CIDR to a string.
452  *
453  * The string format uses quad-dotted notation of four bytes in the address with the length of prefix (e.g.,
454  * "127.0.0.1/32").
455  *
456  * If the resulting string does not fit in @p aBuffer (within its @p aSize characters), the string will be
457  * truncated but the outputted string is always null-terminated.
458  *
459  * @param[in]  aCidr     A pointer to an IPv4 CIDR (MUST NOT be NULL).
460  * @param[out] aBuffer   A pointer to a char array to output the string (MUST NOT be `nullptr`).
461  * @param[in]  aSize     The size of @p aBuffer (in bytes).
462  *
463  */
464 void otIp4CidrToString(const otIp4Cidr *aCidr, char *aBuffer, uint16_t aSize);
465 
466 /**
467  * Converts a human-readable IPv4 address string into a binary representation.
468  *
469  * @param[in]   aString   A pointer to a NULL-terminated string.
470  * @param[out]  aAddress  A pointer to an IPv4 address.
471  *
472  * @retval OT_ERROR_NONE          Successfully parsed the string.
473  * @retval OT_ERROR_INVALID_ARGS  Failed to parse the string.
474  *
475  */
476 otError otIp4AddressFromString(const char *aString, otIp4Address *aAddress);
477 
478 /**
479  * Sets the IPv6 address by performing NAT64 address translation from the preferred NAT64 prefix and the given IPv4
480  * address as specified in RFC 6052.
481  *
482  * @param[in]   aInstance    A pointer to an OpenThread instance.
483  * @param[in]   aIp4Address  A pointer to the IPv4 address to translate to IPv6.
484  * @param[out]  aIp6Address  A pointer to the synthesized IPv6 address.
485  *
486  * @returns  OT_ERROR_NONE           Successfully synthesized the IPv6 address from NAT64 prefix and IPv4 address.
487  * @returns  OT_ERROR_INVALID_STATE  No valid NAT64 prefix in the network data.
488  *
489  */
490 otError otNat64SynthesizeIp6Address(otInstance *aInstance, const otIp4Address *aIp4Address, otIp6Address *aIp6Address);
491 
492 /**
493  * @}
494  *
495  */
496 
497 #ifdef __cplusplus
498 }
499 #endif
500 
501 #endif // OPENTHREAD_NAT64_H_
502