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 otIp4Address mIp4; ///< The IPv4 address of the mapping. 163 otIp6Address mIp6; ///< The IPv6 address of the mapping. 164 165 /** The source port or ICMP ID of the mapping. Used when 166 * OPENTHREAD_CONFIG_NAT64_PORT_TRANSLATION_ENABLE is true. 167 */ 168 uint16_t mSrcPortOrId; 169 170 /** The translated port or ICMP ID of the mapping. Used when 171 * OPENTHREAD_CONFIG_NAT64_PORT_TRANSLATION_ENABLE is true. 172 */ 173 uint16_t mTranslatedPortOrId; 174 uint32_t mRemainingTimeMs; ///< Remaining time before expiry in milliseconds. 175 176 otNat64ProtocolCounters mCounters; 177 } otNat64AddressMapping; 178 179 /** 180 * Used to iterate through NAT64 address mappings. 181 * 182 * The fields in this type are opaque (intended for use by OpenThread core only) and therefore should not be 183 * accessed or used by caller. 184 * 185 * Before using an iterator, it MUST be initialized using `otNat64AddressMappingIteratorInit()`. 186 */ 187 typedef struct otNat64AddressMappingIterator 188 { 189 void *mPtr; 190 } otNat64AddressMappingIterator; 191 192 /** 193 * Initializes an `otNat64AddressMappingIterator`. 194 * 195 * An iterator MUST be initialized before it is used. 196 * 197 * An iterator can be initialized again to restart from the beginning of the mapping info. 198 * 199 * @param[in] aInstance The OpenThread instance. 200 * @param[out] aIterator A pointer to the iterator to initialize. 201 */ 202 void otNat64InitAddressMappingIterator(otInstance *aInstance, otNat64AddressMappingIterator *aIterator); 203 204 /** 205 * Gets the next AddressMapping info (using an iterator). 206 * 207 * Available when `OPENTHREAD_CONFIG_NAT64_TRANSLATOR_ENABLE` is enabled. 208 * 209 * @param[in] aInstance A pointer to an OpenThread instance. 210 * @param[in,out] aIterator A pointer to the iterator. On success the iterator will be updated to point to next 211 * NAT64 address mapping record. To get the first entry the iterator should be set to 212 * OT_NAT64_ADDRESS_MAPPING_ITERATOR_INIT. 213 * @param[out] aMapping A pointer to an `otNat64AddressMapping` where information of next NAT64 address 214 * mapping record is placed (on success). 215 * 216 * @retval OT_ERROR_NONE Successfully found the next NAT64 address mapping info (@p aMapping was successfully 217 * updated). 218 * @retval OT_ERROR_NOT_FOUND No subsequent NAT64 address mapping info was found. 219 */ 220 otError otNat64GetNextAddressMapping(otInstance *aInstance, 221 otNat64AddressMappingIterator *aIterator, 222 otNat64AddressMapping *aMapping); 223 224 /** 225 * States of NAT64. 226 */ 227 typedef enum 228 { 229 OT_NAT64_STATE_DISABLED = 0, ///< NAT64 is disabled. 230 OT_NAT64_STATE_NOT_RUNNING, ///< NAT64 is enabled, but one or more dependencies of NAT64 are not running. 231 OT_NAT64_STATE_IDLE, ///< NAT64 is enabled, but this BR is not an active NAT64 BR. 232 OT_NAT64_STATE_ACTIVE, ///< The BR is publishing a NAT64 prefix and/or translating packets. 233 } otNat64State; 234 235 /** 236 * Gets the state of NAT64 translator. 237 * 238 * Available when `OPENTHREAD_CONFIG_NAT64_TRANSLATOR_ENABLE` is enabled. 239 * 240 * @param[in] aInstance A pointer to an OpenThread instance. 241 * 242 * @retval OT_NAT64_STATE_DISABLED NAT64 translator is disabled. 243 * @retval OT_NAT64_STATE_NOT_RUNNING NAT64 translator is enabled, but the translator is not configured with a valid 244 * NAT64 prefix and a CIDR. 245 * @retval OT_NAT64_STATE_ACTIVE NAT64 translator is enabled, and is translating packets. 246 */ 247 otNat64State otNat64GetTranslatorState(otInstance *aInstance); 248 249 /** 250 * Gets the state of NAT64 prefix manager. 251 * 252 * Available when `OPENTHREAD_CONFIG_NAT64_BORDER_ROUTING_ENABLE` is enabled. 253 * 254 * @param[in] aInstance A pointer to an OpenThread instance. 255 * 256 * @retval OT_NAT64_STATE_DISABLED NAT64 prefix manager is disabled. 257 * @retval OT_NAT64_STATE_NOT_RUNNING NAT64 prefix manager is enabled, but is not running (because the routing manager 258 * is not running). 259 * @retval OT_NAT64_STATE_IDLE NAT64 prefix manager is enabled, but is not publishing a NAT64 prefix. Usually 260 * when there is another border router publishing a NAT64 prefix with higher 261 * priority. 262 * @retval OT_NAT64_STATE_ACTIVE NAT64 prefix manager is enabled, and is publishing NAT64 prefix to the Thread 263 * network. 264 */ 265 otNat64State otNat64GetPrefixManagerState(otInstance *aInstance); 266 267 /** 268 * Enable or disable NAT64 functions. 269 * 270 * Note: This includes the NAT64 Translator (when `OPENTHREAD_CONFIG_NAT64_TRANSLATOR_ENABLE` is enabled) and the NAT64 271 * Prefix Manager (when `OPENTHREAD_CONFIG_NAT64_BORDER_ROUTING_ENABLE` is enabled). 272 * 273 * When `OPENTHREAD_CONFIG_NAT64_TRANSLATOR_ENABLE` is enabled, setting disabled to true resets the 274 * mapping table in the translator. 275 * 276 * Available when `OPENTHREAD_CONFIG_NAT64_TRANSLATOR_ENABLE` or `OPENTHREAD_CONFIG_NAT64_BORDER_ROUTING_ENABLE` is 277 * enabled. 278 * 279 * @param[in] aInstance A pointer to an OpenThread instance. 280 * @param[in] aEnabled A boolean to enable/disable the NAT64 functions 281 * 282 * @sa otNat64GetTranslatorState 283 * @sa otNat64GetPrefixManagerState 284 */ 285 void otNat64SetEnabled(otInstance *aInstance, bool aEnabled); 286 287 /** 288 * Allocate a new message buffer for sending an IPv4 message to the NAT64 translator. 289 * 290 * Message buffers allocated by this function will have 20 bytes (difference between the size of IPv6 headers 291 * and IPv4 header sizes) reserved. 292 * 293 * Available when `OPENTHREAD_CONFIG_NAT64_TRANSLATOR_ENABLE` is enabled. 294 * 295 * @note If @p aSettings is `NULL`, the link layer security is enabled and the message priority is set to 296 * OT_MESSAGE_PRIORITY_NORMAL by default. 297 * 298 * @param[in] aInstance A pointer to an OpenThread instance. 299 * @param[in] aSettings A pointer to the message settings or NULL to set default settings. 300 * 301 * @returns A pointer to the message buffer or NULL if no message buffers are available or parameters are invalid. 302 * 303 * @sa otNat64Send 304 */ 305 otMessage *otIp4NewMessage(otInstance *aInstance, const otMessageSettings *aSettings); 306 307 /** 308 * Sets the CIDR used when setting the source address of the outgoing translated IPv4 packets. 309 * 310 * Is available only when OPENTHREAD_CONFIG_NAT64_TRANSLATOR_ENABLE is enabled. 311 * 312 * @note A valid CIDR must have a non-zero prefix length. The actual addresses pool is limited by the size of the 313 * mapping pool and the number of addresses available in the CIDR block. 314 * 315 * @note This function can be called at any time, but the NAT64 translator will be reset and all existing sessions will 316 * be expired when updating the configured CIDR. 317 * 318 * @param[in] aInstance A pointer to an OpenThread instance. 319 * @param[in] aCidr A pointer to an otIp4Cidr for the IPv4 CIDR block for NAT64. 320 * 321 * @retval OT_ERROR_INVALID_ARGS The given CIDR is not a valid IPv4 CIDR for NAT64. 322 * @retval OT_ERROR_NONE Successfully set the CIDR for NAT64. 323 * 324 * @sa otNat64Send 325 * @sa otNat64SetReceiveIp4Callback 326 */ 327 otError otNat64SetIp4Cidr(otInstance *aInstance, const otIp4Cidr *aCidr); 328 329 /** 330 * Clears the CIDR used when setting the source address of the outgoing translated IPv4 packets. 331 * 332 * Is available only when OPENTHREAD_CONFIG_NAT64_TRANSLATOR_ENABLE is enabled. 333 * 334 * @note This function can be called at any time, but the NAT64 translator will be reset and all existing sessions 335 * will be expired when clearing the configured CIDR. 336 * 337 * @param[in] aInstance A pointer to an OpenThread instance. 338 * 339 * @sa otNat64SetIp4Cidr 340 */ 341 void otNat64ClearIp4Cidr(otInstance *aInstance); 342 343 /** 344 * Translates an IPv4 datagram to an IPv6 datagram and sends via the Thread interface. 345 * 346 * The caller transfers ownership of @p aMessage when making this call. OpenThread will free @p aMessage when 347 * processing is complete, including when a value other than `OT_ERROR_NONE` is returned. 348 * 349 * @param[in] aInstance A pointer to an OpenThread instance. 350 * @param[in] aMessage A pointer to the message buffer containing the IPv4 datagram. 351 * 352 * @retval OT_ERROR_NONE Successfully processed the message. 353 * @retval OT_ERROR_DROP Message was well-formed but not fully processed due to packet processing 354 * rules. 355 * @retval OT_ERROR_NO_BUFS Could not allocate necessary message buffers when processing the datagram. 356 * @retval OT_ERROR_NO_ROUTE No route to host. 357 * @retval OT_ERROR_INVALID_SOURCE_ADDRESS Source address is invalid, e.g. an anycast address or a multicast address. 358 * @retval OT_ERROR_PARSE Encountered a malformed header when processing the message. 359 */ 360 otError otNat64Send(otInstance *aInstance, otMessage *aMessage); 361 362 /** 363 * Pointer is called when an IPv4 datagram (translated by NAT64 translator) is received. 364 * 365 * @param[in] aMessage A pointer to the message buffer containing the received IPv6 datagram. This function transfers 366 * the ownership of the @p aMessage to the receiver of the callback. The message should be 367 * freed by the receiver of the callback after it is processed. 368 * @param[in] aContext A pointer to application-specific context. 369 */ 370 typedef void (*otNat64ReceiveIp4Callback)(otMessage *aMessage, void *aContext); 371 372 /** 373 * Registers a callback to provide received IPv4 datagrams. 374 * 375 * @param[in] aInstance A pointer to an OpenThread instance. 376 * @param[in] aCallback A pointer to a function that is called when an IPv4 datagram is received or 377 * NULL to disable the callback. 378 * @param[in] aContext A pointer to application-specific context. 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 otError otNat64GetCidr(otInstance *aInstance, otIp4Cidr *aCidr); 391 392 /** 393 * Test if two IPv4 addresses are the same. 394 * 395 * @param[in] aFirst A pointer to the first IPv4 address to compare. 396 * @param[in] aSecond A pointer to the second IPv4 address to compare. 397 * 398 * @retval TRUE The two IPv4 addresses are the same. 399 * @retval FALSE The two IPv4 addresses are not the same. 400 */ 401 bool otIp4IsAddressEqual(const otIp4Address *aFirst, const otIp4Address *aSecond); 402 403 /** 404 * Set @p aIp4Address by performing NAT64 address translation from @p aIp6Address as specified 405 * in RFC 6052. 406 * 407 * The NAT64 @p aPrefixLength MUST be one of the following values: 32, 40, 48, 56, 64, or 96, otherwise the behavior 408 * of this method is undefined. 409 * 410 * @param[in] aPrefixLength The prefix length to use for IPv4/IPv6 translation. 411 * @param[in] aIp6Address A pointer to an IPv6 address. 412 * @param[out] aIp4Address A pointer to output the IPv4 address. 413 */ 414 void otIp4ExtractFromIp6Address(uint8_t aPrefixLength, const otIp6Address *aIp6Address, otIp4Address *aIp4Address); 415 416 /** 417 * Extracts the IPv4 address from a given IPv4-mapped IPv6 address. 418 * 419 * An IPv4-mapped IPv6 address consists of an 80-bit prefix of zeros, the next 16 bits set to ones, and the remaining, 420 * least-significant 32 bits contain the IPv4 address, e.g., `::ffff:192.0.2.128` representing `192.0.2.128`. 421 * 422 * @param[in] aIp6Address An IPv6 address to extract IPv4 from. 423 * @param[out] aIp4Address An IPv4 address to output the extracted address. 424 * 425 * @retval OT_ERROR_NONE Extracted the IPv4 address successfully. @p aIp4Address is updated. 426 * @retval OT_ERROR_PARSE The @p aIp6Address does not follow the IPv4-mapped IPv6 address format. 427 */ 428 otError otIp4FromIp4MappedIp6Address(const otIp6Address *aIp6Address, otIp4Address *aIp4Address); 429 430 /** 431 * Converts a given IP4 address to an IPv6 address following the IPv4-mapped IPv6 address format. 432 * 433 * @param[in] aIp4Address An IPv4 address to convert. 434 * @param[out] aIp6Address An IPv6 address to set. 435 */ 436 void otIp4ToIp4MappedIp6Address(const otIp4Address *aIp4Address, otIp6Address *aIp6Address); 437 438 #define OT_IP4_ADDRESS_STRING_SIZE 17 ///< Length of 000.000.000.000 plus a suffix NUL 439 440 /** 441 * Converts the address to a string. 442 * 443 * The string format uses quad-dotted notation of four bytes in the address (e.g., "127.0.0.1"). 444 * 445 * If the resulting string does not fit in @p aBuffer (within its @p aSize characters), the string will be 446 * truncated but the outputted string is always null-terminated. 447 * 448 * @param[in] aAddress A pointer to an IPv4 address (MUST NOT be NULL). 449 * @param[out] aBuffer A pointer to a char array to output the string (MUST NOT be `nullptr`). 450 * @param[in] aSize The size of @p aBuffer (in bytes). 451 */ 452 void otIp4AddressToString(const otIp4Address *aAddress, char *aBuffer, uint16_t aSize); 453 454 #define OT_IP4_CIDR_STRING_SIZE 20 ///< Length of 000.000.000.000/00 plus a suffix NUL 455 456 /** 457 * Converts a human-readable IPv4 CIDR string into a binary representation. 458 * 459 * @param[in] aString A pointer to a NULL-terminated string. 460 * @param[out] aCidr A pointer to an IPv4 CIDR. 461 * 462 * @retval OT_ERROR_NONE Successfully parsed the string. 463 * @retval OT_ERROR_INVALID_ARGS Failed to parse the string. 464 */ 465 otError otIp4CidrFromString(const char *aString, otIp4Cidr *aCidr); 466 467 /** 468 * Converts the IPv4 CIDR to a string. 469 * 470 * The string format uses quad-dotted notation of four bytes in the address with the length of prefix (e.g., 471 * "127.0.0.1/32"). 472 * 473 * If the resulting string does not fit in @p aBuffer (within its @p aSize characters), the string will be 474 * truncated but the outputted string is always null-terminated. 475 * 476 * @param[in] aCidr A pointer to an IPv4 CIDR (MUST NOT be NULL). 477 * @param[out] aBuffer A pointer to a char array to output the string (MUST NOT be `nullptr`). 478 * @param[in] aSize The size of @p aBuffer (in bytes). 479 */ 480 void otIp4CidrToString(const otIp4Cidr *aCidr, char *aBuffer, uint16_t aSize); 481 482 /** 483 * Converts a human-readable IPv4 address string into a binary representation. 484 * 485 * @param[in] aString A pointer to a NULL-terminated string. 486 * @param[out] aAddress A pointer to an IPv4 address. 487 * 488 * @retval OT_ERROR_NONE Successfully parsed the string. 489 * @retval OT_ERROR_INVALID_ARGS Failed to parse the string. 490 */ 491 otError otIp4AddressFromString(const char *aString, otIp4Address *aAddress); 492 493 /** 494 * Sets the IPv6 address by performing NAT64 address translation from the preferred NAT64 prefix and the given IPv4 495 * address as specified in RFC 6052. 496 * 497 * @param[in] aInstance A pointer to an OpenThread instance. 498 * @param[in] aIp4Address A pointer to the IPv4 address to translate to IPv6. 499 * @param[out] aIp6Address A pointer to the synthesized IPv6 address. 500 * 501 * @returns OT_ERROR_NONE Successfully synthesized the IPv6 address from NAT64 prefix and IPv4 address. 502 * @returns OT_ERROR_INVALID_STATE No valid NAT64 prefix in the network data. 503 */ 504 otError otNat64SynthesizeIp6Address(otInstance *aInstance, const otIp4Address *aIp4Address, otIp6Address *aIp6Address); 505 506 /** 507 * @} 508 */ 509 510 #ifdef __cplusplus 511 } 512 #endif 513 514 #endif // OPENTHREAD_NAT64_H_ 515