mirror of
https://github.com/espressif/openthread.git
synced 2026-07-27 22:37:45 +00:00
[nat64] prevent IPv4 addr sharing when port translation is disabled (#11865)
The logic for sharing an IPv4 address, intended for scenarios with a small address pool (CIDR prefix > /28), was incorrectly being applied even when port translation was disabled. When `OPENTHREAD_CONFIG_NAT64_PORT_TRANSLATION_ENABLE` is disabled, each mapping requires a unique IPv4 address. The previous implementation would incorrectly reuse the same address from the pool. This commit makes the address sharing logic conditional on the `OPENTHREAD_CONFIG_NAT64_PORT_TRANSLATION_ENABLE` configuration. When disabled, the translator now correctly allocates a unique IPv4 address for each mapping and returns it to the pool upon release.
This commit is contained in:
@@ -381,12 +381,17 @@ void Translator::Mapping::CopyTo(AddressMapping &aMapping, TimeMilli aNow) const
|
||||
|
||||
void Translator::ReleaseMapping(Mapping &aMapping)
|
||||
{
|
||||
if (mIp4Cidr.mLength <= kMaxCidrLenForValidAddrPool)
|
||||
#if OPENTHREAD_CONFIG_NAT64_PORT_TRANSLATION_ENABLE
|
||||
if (mIp4Cidr.mLength > kAddressMappingCidrLimit)
|
||||
{
|
||||
// If `CONFIG_NAT64_PORT_TRANSLATION_ENABLE` is enabled
|
||||
// IPv4 addresses are allocated from the pool only when the
|
||||
// pool size is above a minimum value. Otherwise use just the
|
||||
// first address from the list and we are not removing it
|
||||
// from the array.
|
||||
// first address from the pool.
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
IgnoreError(mIp4AddressPool.PushBack(aMapping.mIp4Address));
|
||||
}
|
||||
|
||||
@@ -450,7 +455,9 @@ Translator::Mapping *Translator::AllocateMapping(const Ip6::Headers &aIp6Headers
|
||||
Mapping *mapping = nullptr;
|
||||
Ip4::Address ip4Addr;
|
||||
|
||||
// The NAT64 translator can work in 2 ways, either with a single
|
||||
#if OPENTHREAD_CONFIG_NAT64_PORT_TRANSLATION_ENABLE
|
||||
// When port translation (`NAT64_PORT_TRANSLATION`) is enabled
|
||||
// the NAT64 translator can work in 2 ways, either with a single
|
||||
// IPv4 address or a larger pool of addresses. There is also the
|
||||
// corner case where the address pool is generated from a big
|
||||
// CIDR length and the number of available IPv4 addresses is not
|
||||
@@ -461,12 +468,13 @@ Translator::Mapping *Translator::AllocateMapping(const Ip6::Headers &aIp6Headers
|
||||
// larger pool is available each active mapping will use a
|
||||
// separate IPv4 address.
|
||||
|
||||
if (mIp4Cidr.mLength > kMaxCidrLenForValidAddrPool)
|
||||
if (mIp4Cidr.mLength > kAddressMappingCidrLimit)
|
||||
{
|
||||
// TODO: add logic to cycle between available IPv4 addresses
|
||||
ip4Addr = *mIp4AddressPool.At(0);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
if (mIp4AddressPool.IsEmpty())
|
||||
{
|
||||
@@ -475,6 +483,7 @@ Translator::Mapping *Translator::AllocateMapping(const Ip6::Headers &aIp6Headers
|
||||
|
||||
VerifyOrExit(ReleaseExpiredMappings() > 0);
|
||||
}
|
||||
|
||||
ip4Addr = *mIp4AddressPool.PopBack();
|
||||
}
|
||||
|
||||
|
||||
@@ -296,13 +296,26 @@ private:
|
||||
static constexpr uint32_t kIdleTimeout = OPENTHREAD_CONFIG_NAT64_IDLE_TIMEOUT_SECONDS * Time::kOneSecondInMsec;
|
||||
static constexpr uint32_t kIcmpTimeout = OPENTHREAD_CONFIG_NAT64_ICMP_IDLE_TIMEOUT_SECONDS * Time::kOneSecondInMsec;
|
||||
|
||||
static constexpr uint32_t kPoolSize = OPENTHREAD_CONFIG_NAT64_MAX_MAPPINGS;
|
||||
static constexpr uint32_t kPoolSize = OPENTHREAD_CONFIG_NAT64_MAX_MAPPINGS;
|
||||
|
||||
#if OPENTHREAD_CONFIG_NAT64_PORT_TRANSLATION_ENABLE
|
||||
// Under `PORT_TRANSLATION_ENABLE`, the translator can operate in
|
||||
// two modes: 1-to-1 address mapping where each IPv6 address gets
|
||||
// a unique IPv4 address from a pool, or having the mappings
|
||||
// share one (or a few) IPv4 addresses and are distinguished by
|
||||
// the translated port numbers.
|
||||
//
|
||||
// This constant defines the maximum allowed CIDR prefix length
|
||||
// for the IPv4 address pool to be considered large enough to use
|
||||
// 1-to-1 address mapping. If the configured prefix length is
|
||||
// greater than this value (e.g., /29, /30), the address pool is
|
||||
// too small, and the translator will fall back to using port
|
||||
// translation.
|
||||
static constexpr uint8_t kAddressMappingCidrLimit = 28;
|
||||
|
||||
static constexpr uint16_t kMinTranslationPort = 49152;
|
||||
static constexpr uint16_t kMaxTranslationPort = 65535;
|
||||
|
||||
// The maximum value the CIDR len can have in order to have a big
|
||||
// enough pool to support a minimal number of devices
|
||||
static constexpr uint8_t kMaxCidrLenForValidAddrPool = 28;
|
||||
#endif
|
||||
|
||||
static constexpr DropReason kReasonUnknown = OT_NAT64_DROP_REASON_UNKNOWN;
|
||||
static constexpr DropReason kReasonIllegalPacket = OT_NAT64_DROP_REASON_ILLEGAL_PACKET;
|
||||
|
||||
Reference in New Issue
Block a user