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