diff --git a/src/inet/IPAddress.cpp b/src/inet/IPAddress.cpp index ce65f7875e811f..c5fabfeb9958fd 100644 --- a/src/inet/IPAddress.cpp +++ b/src/inet/IPAddress.cpp @@ -33,7 +33,9 @@ #include +#include #include +#include #include "arpa-inet-compatibility.h" @@ -127,28 +129,58 @@ ip_addr_t IPAddress::ToLwIPAddr(void) const { #if INET_CONFIG_ENABLE_IPV4 case IPAddressType::kIPv4: - IP_SET_TYPE_VAL(ret, IPADDR_TYPE_V4); - *ip_2_ip4(&ret) = IPAddress::ToIPv4(); + ip_addr_copy_from_ip4(ret, IPAddress::ToIPv4()); break; #endif // INET_CONFIG_ENABLE_IPV4 case IPAddressType::kIPv6: - IP_SET_TYPE_VAL(ret, IPADDR_TYPE_V6); - *ip_2_ip6(&ret) = IPAddress::ToIPv6(); + ip_addr_copy_from_ip6(ret, IPAddress::ToIPv6()); break; default: -#if INET_CONFIG_ENABLE_IPV4 - ret = *IP_ADDR_ANY; -#else ret = *IP6_ADDR_ANY; -#endif break; } return ret; } +CHIP_ERROR IPAddress::ToLwIPAddr(IPAddressType addressType, ip_addr_t & outAddress) const +{ + VerifyOrReturnError(addressType != IPAddressType::kUnknown, CHIP_ERROR_INVALID_ARGUMENT); + + switch (Type()) + { +#if INET_CONFIG_ENABLE_IPV4 + case IPAddressType::kIPv4: + ip_addr_copy_from_ip4(outAddress, IPAddress::ToIPv4()); + return (addressType == IPAddressType::kIPv6) ? INET_ERROR_WRONG_ADDRESS_TYPE : CHIP_NO_ERROR; +#endif // INET_CONFIG_ENABLE_IPV4 + + case IPAddressType::kIPv6: + ip_addr_copy_from_ip6(outAddress, IPAddress::ToIPv6()); +#if INET_CONFIG_ENABLE_IPV4 + return (addressType == IPAddressType::kIPv4) ? INET_ERROR_WRONG_ADDRESS_TYPE : CHIP_NO_ERROR; +#else + return CHIP_NO_ERROR; +#endif // INET_CONFIG_ENABLE_IPV4 + + case IPAddressType::kAny: +#if INET_CONFIG_ENABLE_IPV4 + if (addressType == IPAddressType::kIPv4) + { + outAddress = *IP4_ADDR_ANY; + return CHIP_NO_ERROR; + } +#endif // INET_CONFIG_ENABLE_IPV4 + outAddress = *IP6_ADDR_ANY; + return CHIP_NO_ERROR; + + default: + return INET_ERROR_WRONG_ADDRESS_TYPE; + } +} + lwip_ip_addr_type IPAddress::ToLwIPAddrType(IPAddressType typ) { lwip_ip_addr_type ret; diff --git a/src/inet/IPAddress.h b/src/inet/IPAddress.h index 3b502a8293a1fc..db9f7bb06d255e 100644 --- a/src/inet/IPAddress.h +++ b/src/inet/IPAddress.h @@ -33,6 +33,7 @@ #include #include +#include #include #include @@ -485,6 +486,15 @@ class DLL_EXPORT IPAddress */ ip_addr_t ToLwIPAddr(void) const; + /** + * Extract the IP address as a LwIP ip_addr_t structure. + * + * If the IP address is Any, the result is IP6_ADDR_ANY unless the requested addressType is kIPv4. + * If the requested addressType is IPAddressType::kAny, extracts the IP address as an LwIP ip_addr_t structure. + * Otherwise, returns INET_ERROR_WRONG_ADDRESS_TYPE if the requested addressType does not match the IP address. + */ + CHIP_ERROR ToLwIPAddr(IPAddressType addressType, ip_addr_t & outAddress) const; + /** * @brief Convert the INET layer address type to its underlying LwIP type. * diff --git a/src/inet/TCPEndPointImplLwIP.cpp b/src/inet/TCPEndPointImplLwIP.cpp index 6fb08a8ffd3d1a..cc454552b3fb32 100644 --- a/src/inet/TCPEndPointImplLwIP.cpp +++ b/src/inet/TCPEndPointImplLwIP.cpp @@ -67,30 +67,18 @@ CHIP_ERROR TCPEndPointImplLwIP::BindImpl(IPAddressType addrType, const IPAddress CHIP_ERROR res = GetPCB(addrType); // Bind the PCB to the specified address/port. + ip_addr_t ipAddr; if (res == CHIP_NO_ERROR) { if (reuseAddr) { ip_set_option(mTCP, SOF_REUSEADDR); } + res = addr.ToLwIPAddr(addrType, ipAddr); + } - ip_addr_t ipAddr; - if (addr != IPAddress::Any) - { - ipAddr = addr.ToLwIPAddr(); - } - else if (addrType == IPAddressType::kIPv6) - { - ipAddr = ip6_addr_any; - } -#if INET_CONFIG_ENABLE_IPV4 - else if (addrType == IPAddressType::kIPv4) - { - ipAddr = ip_addr_any; - } -#endif // INET_CONFIG_ENABLE_IPV4 - else - res = INET_ERROR_WRONG_ADDRESS_TYPE; + if (res == CHIP_NO_ERROR) + { res = chip::System::MapErrorLwIP(tcp_bind(mTCP, &ipAddr, port)); } diff --git a/src/inet/UDPEndPointImplLwIP.cpp b/src/inet/UDPEndPointImplLwIP.cpp index e5f74911bbd0a1..f21185741ceeaa 100644 --- a/src/inet/UDPEndPointImplLwIP.cpp +++ b/src/inet/UDPEndPointImplLwIP.cpp @@ -72,22 +72,14 @@ CHIP_ERROR UDPEndPointImplLwIP::BindImpl(IPAddressType addressType, const IPAddr CHIP_ERROR res = GetPCB(addressType); // Bind the PCB to the specified address/port. + ip_addr_t ipAddr; if (res == CHIP_NO_ERROR) { - ip_addr_t ipAddr = address.ToLwIPAddr(); - - // TODO: IPAddress ANY has only one constant state, however addressType - // has separate IPV4 and IPV6 'any' settings. This tries to correct - // for this as LWIP default if IPv4 is compiled in is to consider - // 'any == any_v4' - // - // We may want to consider having separate AnyV4 and AnyV6 constants - // inside CHIP to resolve this ambiguity - if ((address.Type() == IPAddressType::kAny) && (addressType == IPAddressType::kIPv6)) - { - ipAddr = *IP6_ADDR_ANY; - } + res = address.ToLwIPAddr(addressType, ipAddr); + } + if (res == CHIP_NO_ERROR) + { res = chip::System::MapErrorLwIP(udp_bind(mUDP, &ipAddr, port)); } diff --git a/src/inet/tests/TestInetAddress.cpp b/src/inet/tests/TestInetAddress.cpp index f29ca49e2b5327..0710a57e39e12d 100644 --- a/src/inet/tests/TestInetAddress.cpp +++ b/src/inet/tests/TestInetAddress.cpp @@ -44,6 +44,7 @@ #include #include +#include #include #include @@ -1710,6 +1711,109 @@ void CheckIPPrefix(nlTestSuite * inSuite, void * inContext) } } +#if CHIP_SYSTEM_CONFIG_USE_LWIP + +bool sameLwIPAddress(const ip6_addr_t & a, const ip6_addr_t & b) +{ + return (a.addr[0] == b.addr[0]) && (a.addr[1] == b.addr[1]) && (a.addr[2] == b.addr[2]) && (a.addr[3] == b.addr[3]); +} + +#if LWIP_IPV4 && LWIP_IPV6 +bool sameLwIPAddress(const ip_addr_t & a, const ip_addr_t & b) +{ + switch (a.type) + { + case IPADDR_TYPE_V4: + return (b.type == IPADDR_TYPE_V4) && (a.u_addr.ip4.addr == b.u_addr.ip4.addr); + case IPADDR_TYPE_V6: + return (b.type == IPADDR_TYPE_V6) && sameLwIPAddress(a.u_addr.ip6, b.u_addr.ip6); + default: + return false; + } +} +#endif // LWIP_IPV4 && LWIP_IPV6 + +/** + * Test ToLwIPAddress() + */ +void CheckToLwIPAddr(nlTestSuite * inSuite, void * inContext) +{ + const struct TestContext * lContext = static_cast(inContext); + IPAddressExpandedContextIterator lCurrent = lContext->mIPAddressExpandedContextRange.mBegin; + IPAddressExpandedContextIterator lEnd = lContext->mIPAddressExpandedContextRange.mEnd; + CHIP_ERROR err; + ip_addr_t lwip_expected_addr, lwip_check_addr; + + while (lCurrent != lEnd) + { + IPAddress test_addr; + + SetupIPAddress(test_addr, lCurrent); + +#if INET_CONFIG_ENABLE_IPV4 + if (lCurrent->mAddr.mAddrType == IPAddressType::kIPv4) + { + ip_addr_copy_from_ip4(lwip_expected_addr, test_addr.ToIPv4()); + lwip_check_addr = test_addr.ToLwIPAddr(); + NL_TEST_ASSERT(inSuite, sameLwIPAddress(lwip_expected_addr, lwip_check_addr)); + + err = test_addr.ToLwIPAddr(IPAddressType::kAny, lwip_check_addr); + NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); + NL_TEST_ASSERT(inSuite, sameLwIPAddress(lwip_expected_addr, lwip_check_addr)); + + err = test_addr.ToLwIPAddr(IPAddressType::kIPv4, lwip_check_addr); + NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); + NL_TEST_ASSERT(inSuite, sameLwIPAddress(lwip_expected_addr, lwip_check_addr)); + + err = test_addr.ToLwIPAddr(IPAddressType::kIPv6, lwip_check_addr); + NL_TEST_ASSERT(inSuite, err == INET_ERROR_WRONG_ADDRESS_TYPE); + } + else +#endif // INET_CONFIG_ENABLE_IPV4 + if (lCurrent->mAddr.mAddrType == IPAddressType::kIPv6) + { + ip_addr_copy_from_ip6(lwip_expected_addr, test_addr.ToIPv6()); + lwip_check_addr = test_addr.ToLwIPAddr(); + NL_TEST_ASSERT(inSuite, sameLwIPAddress(lwip_expected_addr, lwip_check_addr)); + + err = test_addr.ToLwIPAddr(IPAddressType::kAny, lwip_check_addr); + NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); + NL_TEST_ASSERT(inSuite, sameLwIPAddress(lwip_expected_addr, lwip_check_addr)); + + err = test_addr.ToLwIPAddr(IPAddressType::kIPv6, lwip_check_addr); + NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); + NL_TEST_ASSERT(inSuite, sameLwIPAddress(lwip_expected_addr, lwip_check_addr)); + +#if INET_CONFIG_ENABLE_IPV4 + err = test_addr.ToLwIPAddr(IPAddressType::kIPv4, lwip_check_addr); + NL_TEST_ASSERT(inSuite, err == INET_ERROR_WRONG_ADDRESS_TYPE); +#endif // INET_CONFIG_ENABLE_IPV4 + } + else if (lCurrent->mAddr.mAddrType == IPAddressType::kAny) + { + lwip_check_addr = test_addr.ToLwIPAddr(); + NL_TEST_ASSERT(inSuite, sameLwIPAddress(*IP6_ADDR_ANY, lwip_check_addr)); + + err = test_addr.ToLwIPAddr(IPAddressType::kAny, lwip_check_addr); + NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); + NL_TEST_ASSERT(inSuite, sameLwIPAddress(*IP6_ADDR_ANY, lwip_check_addr)); + + err = test_addr.ToLwIPAddr(IPAddressType::kIPv6, lwip_check_addr); + NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); + NL_TEST_ASSERT(inSuite, sameLwIPAddress(*IP6_ADDR_ANY, lwip_check_addr)); + +#if INET_CONFIG_ENABLE_IPV4 + err = test_addr.ToLwIPAddr(IPAddressType::kIPv4, lwip_check_addr); + NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); + NL_TEST_ASSERT(inSuite, sameLwIPAddress(*IP4_ADDR_ANY, lwip_check_addr)); +#endif // INET_CONFIG_ENABLE_IPV4 + } + + ++lCurrent; + } +} +#endif // CHIP_SYSTEM_CONFIG_USE_LWIP + /** * Test Suite. It lists all the test functions. */ @@ -1750,6 +1854,9 @@ const nlTest sTests[] = NL_TEST_DEF("Assemble IPv6 Transient Multicast address", CheckMakeIPv6TransientMulticast), NL_TEST_DEF("Assemble IPv6 Prefix Multicast address", CheckMakeIPv6PrefixMulticast), NL_TEST_DEF("IPPrefix test", CheckIPPrefix), +#if CHIP_SYSTEM_CONFIG_USE_LWIP + NL_TEST_DEF("Convert IPAddress to LwIP address", CheckToLwIPAddr), +#endif NL_TEST_SENTINEL() }; // clang-format on