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