diff --git a/src/inet/BUILD.gn b/src/inet/BUILD.gn index 1ba8ea5687e2e3..3f81be89647e6f 100644 --- a/src/inet/BUILD.gn +++ b/src/inet/BUILD.gn @@ -141,5 +141,11 @@ static_library("inet") { public_deps += [ "${nlfaultinjection_root}:nlfaultinjection" ] } + if (current_os == "android") { + public_deps += [ "${chip_root}/src/platform/android:inet" ] + } else { + sources += [ "InetInterfaceImplDefault.cpp" ] + } + cflags = [ "-Wconversion" ] } diff --git a/src/inet/InetInterface.cpp b/src/inet/InetInterface.cpp index 4d30309752408e..4a404a29db177c 100644 --- a/src/inet/InetInterface.cpp +++ b/src/inet/InetInterface.cpp @@ -50,6 +50,7 @@ #ifdef HAVE_SYS_SOCKIO_H #include #endif /* HAVE_SYS_SOCKIO_H */ +#include "InetInterfaceImpl.h" #include #include #include @@ -502,140 +503,6 @@ void CloseIOCTLSocket() } } -#ifdef __ANDROID__ - -static struct if_nameindex * backport_if_nameindex(void); -static void backport_if_freenameindex(struct if_nameindex *); - -static void backport_if_freenameindex(struct if_nameindex * inArray) -{ - if (inArray == nullptr) - { - return; - } - - for (size_t i = 0; inArray[i].if_index != 0; i++) - { - if (inArray[i].if_name != nullptr) - { - Platform::MemoryFree(inArray[i].if_name); - } - } - - Platform::MemoryFree(inArray); -} - -static struct if_nameindex * backport_if_nameindex(void) -{ - int err; - size_t intfIter = 0; - size_t maxIntfNum = 0; - size_t numIntf = 0; - size_t numAddrs = 0; - struct if_nameindex * retval = nullptr; - struct if_nameindex * tmpval = nullptr; - struct ifaddrs * addrList = nullptr; - struct ifaddrs * addrIter = nullptr; - const char * lastIntfName = ""; - - err = getifaddrs(&addrList); - VerifyOrExit(err >= 0, ); - - // coalesce on consecutive interface names - for (addrIter = addrList; addrIter != nullptr; addrIter = addrIter->ifa_next) - { - numAddrs++; - if (strcmp(addrIter->ifa_name, lastIntfName) != 0) - { - numIntf++; - lastIntfName = addrIter->ifa_name; - } - } - - tmpval = (struct if_nameindex *) Platform::MemoryAlloc((numIntf + 1) * sizeof(struct if_nameindex)); - VerifyOrExit(tmpval != nullptr, ); - memset(tmpval, 0, (numIntf + 1) * sizeof(struct if_nameindex)); - - lastIntfName = ""; - for (addrIter = addrList; addrIter != nullptr; addrIter = addrIter->ifa_next) - { - if (strcmp(addrIter->ifa_name, lastIntfName) == 0) - { - continue; - } - - unsigned index = if_nametoindex(addrIter->ifa_name); - if (index != 0) - { - tmpval[intfIter].if_index = index; - tmpval[intfIter].if_name = strdup(addrIter->ifa_name); - intfIter++; - } - lastIntfName = addrIter->ifa_name; - } - - // coalesce on interface index - maxIntfNum = 0; - for (size_t i = 0; tmpval[i].if_index != 0; i++) - { - if (maxIntfNum < tmpval[i].if_index) - { - maxIntfNum = tmpval[i].if_index; - } - } - - retval = (struct if_nameindex *) Platform::MemoryAlloc((maxIntfNum + 1) * sizeof(struct if_nameindex)); - VerifyOrExit(retval != nullptr, ); - memset(retval, 0, (maxIntfNum + 1) * sizeof(struct if_nameindex)); - - for (size_t i = 0; tmpval[i].if_index != 0; i++) - { - struct if_nameindex * intf = &tmpval[i]; - if (retval[intf->if_index - 1].if_index == 0) - { - retval[intf->if_index - 1] = *intf; - } - else - { - free(intf->if_name); - intf->if_index = 0; - intf->if_name = 0; - } - } - - intfIter = 0; - - // coalesce potential gaps between indeces - for (size_t i = 0; i < maxIntfNum; i++) - { - if (retval[i].if_index != 0) - { - retval[intfIter] = retval[i]; - intfIter++; - } - } - - for (size_t i = intfIter; i < maxIntfNum; i++) - { - retval[i].if_index = 0; - retval[i].if_name = nullptr; - } - -exit: - if (tmpval != nullptr) - { - Platform::MemoryFree(tmpval); - } - - if (addrList != nullptr) - { - freeifaddrs(addrList); - } - - return retval; -} -#endif // __ANDROID__ - InterfaceIterator::InterfaceIterator() { mIntfArray = nullptr; @@ -648,11 +515,7 @@ InterfaceIterator::~InterfaceIterator() { if (mIntfArray != nullptr) { -#ifdef __ANDROID__ - backport_if_freenameindex(mIntfArray); -#else - if_freenameindex(mIntfArray); -#endif + if_freenameindexImpl(mIntfArray); mIntfArray = nullptr; } } @@ -666,11 +529,7 @@ bool InterfaceIterator::Next() { if (mIntfArray == nullptr) { -#ifdef __ANDROID__ - mIntfArray = backport_if_nameindex(); -#else - mIntfArray = if_nameindex(); -#endif + mIntfArray = if_nameindexImpl(); } else if (mIntfArray[mCurIntf].if_index != 0) { diff --git a/src/inet/InetInterfaceImpl.h b/src/inet/InetInterfaceImpl.h new file mode 100644 index 00000000000000..4d310c998c0107 --- /dev/null +++ b/src/inet/InetInterfaceImpl.h @@ -0,0 +1,34 @@ +/* + * + * Copyright (c) 2020-2023 Project CHIP Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include + +#if CHIP_SYSTEM_CONFIG_USE_SOCKETS && CHIP_SYSTEM_CONFIG_USE_BSD_IFADDRS +#include + +namespace chip { +namespace Inet { +// Some platforms have broken if_nameindex and if_freenameindex implementations. +// Allow platforms to either wrap a non-broken platform implementation or have a custom +// implementation. +struct if_nameindex * if_nameindexImpl(); +void if_freenameindexImpl(struct if_nameindex * inArray); +} // namespace Inet +} // namespace chip +#endif diff --git a/src/inet/InetInterfaceImplDefault.cpp b/src/inet/InetInterfaceImplDefault.cpp new file mode 100644 index 00000000000000..461cbe1b0a3ace --- /dev/null +++ b/src/inet/InetInterfaceImplDefault.cpp @@ -0,0 +1,33 @@ +/* + * + * Copyright (c) 2020-2023 Project CHIP Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include + +#if CHIP_SYSTEM_CONFIG_USE_SOCKETS && CHIP_SYSTEM_CONFIG_USE_BSD_IFADDRS +#include +namespace chip { +namespace Inet { +struct if_nameindex * if_nameindexImpl() +{ + return if_nameindex(); +} +void if_freenameindexImpl(struct if_nameindex * inArray) +{ + if_freenameindex(inArray); +} +} // namespace Inet +} // namespace chip +#endif diff --git a/src/platform/android/BUILD.gn b/src/platform/android/BUILD.gn index 16b21f506f2009..bd9f3cd8316220 100644 --- a/src/platform/android/BUILD.gn +++ b/src/platform/android/BUILD.gn @@ -82,6 +82,11 @@ static_library("android") { public_configs = [] } +source_set("inet") { + sources = [ "InetInterfaceImpl.cpp" ] + deps = [ "${chip_root}/src/lib/support" ] +} + android_library("java") { output_name = "AndroidPlatform.jar" diff --git a/src/platform/android/InetInterfaceImpl.cpp b/src/platform/android/InetInterfaceImpl.cpp new file mode 100644 index 00000000000000..3ff1a242020cc2 --- /dev/null +++ b/src/platform/android/InetInterfaceImpl.cpp @@ -0,0 +1,159 @@ +/* + * + * Copyright (c) 2020-2023 Project CHIP Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#if CHIP_SYSTEM_CONFIG_USE_SOCKETS && CHIP_SYSTEM_CONFIG_USE_BSD_IFADDRS +#include +#include +#include +#include +namespace chip { +namespace Inet { + +using namespace chip; + +void if_freenameindexImpl(struct if_nameindex * inArray) +{ + if (inArray == nullptr) + { + return; + } + + for (size_t i = 0; inArray[i].if_index != 0; i++) + { + if (inArray[i].if_name != nullptr) + { + Platform::MemoryFree(inArray[i].if_name); + } + } + + Platform::MemoryFree(inArray); +} + +struct if_nameindex * if_nameindexImpl() +{ + int err; + size_t intfIter = 0; + size_t maxIntfNum = 0; + size_t numIntf = 0; + size_t numAddrs = 0; + struct if_nameindex * retval = nullptr; + struct if_nameindex * tmpval = nullptr; + struct ifaddrs * addrList = nullptr; + struct ifaddrs * addrIter = nullptr; + const char * lastIntfName = ""; + + err = getifaddrs(&addrList); + VerifyOrExit(err >= 0, ); + + // coalesce on consecutive interface names + for (addrIter = addrList; addrIter != nullptr; addrIter = addrIter->ifa_next) + { + numAddrs++; + if (strcmp(addrIter->ifa_name, lastIntfName) != 0) + { + numIntf++; + lastIntfName = addrIter->ifa_name; + } + } + + tmpval = (struct if_nameindex *) Platform::MemoryAlloc((numIntf + 1) * sizeof(struct if_nameindex)); + VerifyOrExit(tmpval != nullptr, ); + memset(tmpval, 0, (numIntf + 1) * sizeof(struct if_nameindex)); + + lastIntfName = ""; + for (addrIter = addrList; addrIter != nullptr; addrIter = addrIter->ifa_next) + { + if (strcmp(addrIter->ifa_name, lastIntfName) == 0) + { + continue; + } + + unsigned index = if_nametoindex(addrIter->ifa_name); + if (index != 0) + { + tmpval[intfIter].if_index = index; + tmpval[intfIter].if_name = strdup(addrIter->ifa_name); + intfIter++; + } + lastIntfName = addrIter->ifa_name; + } + + // coalesce on interface index + maxIntfNum = 0; + for (size_t i = 0; tmpval[i].if_index != 0; i++) + { + if (maxIntfNum < tmpval[i].if_index) + { + maxIntfNum = tmpval[i].if_index; + } + } + + retval = (struct if_nameindex *) Platform::MemoryAlloc((maxIntfNum + 1) * sizeof(struct if_nameindex)); + VerifyOrExit(retval != nullptr, ); + memset(retval, 0, (maxIntfNum + 1) * sizeof(struct if_nameindex)); + + for (size_t i = 0; tmpval[i].if_index != 0; i++) + { + struct if_nameindex * intf = &tmpval[i]; + if (retval[intf->if_index - 1].if_index == 0) + { + retval[intf->if_index - 1] = *intf; + } + else + { + free(intf->if_name); + intf->if_index = 0; + intf->if_name = 0; + } + } + + intfIter = 0; + + // coalesce potential gaps between indeces + for (size_t i = 0; i < maxIntfNum; i++) + { + if (retval[i].if_index != 0) + { + retval[intfIter] = retval[i]; + intfIter++; + } + } + + for (size_t i = intfIter; i < maxIntfNum; i++) + { + retval[i].if_index = 0; + retval[i].if_name = nullptr; + } + +exit: + if (tmpval != nullptr) + { + Platform::MemoryFree(tmpval); + } + + if (addrList != nullptr) + { + freeifaddrs(addrList); + } + + return retval; +} +} // namespace Inet +} // namespace chip +#endif