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 aEnable); 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] aCallbackContext 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