diff --git a/src/libraries/Native/Unix/System.Native/CMakeLists.txt b/src/libraries/Native/Unix/System.Native/CMakeLists.txt index 9e490e9f0e98e..1b06d83880533 100644 --- a/src/libraries/Native/Unix/System.Native/CMakeLists.txt +++ b/src/libraries/Native/Unix/System.Native/CMakeLists.txt @@ -81,7 +81,6 @@ append_extra_system_libs(NATIVE_LIBS_EXTRA) if (CLR_CMAKE_TARGET_ANDROID AND NOT HAVE_GETIFADDRS) add_definitions(-DANDROID_GETIFADDRS_WORKAROUND) - add_compile_options(-Wno-gnu-zero-variadic-macro-arguments) list (APPEND NATIVE_LIBS_EXTRA -llog) diff --git a/src/libraries/Native/Unix/System.Native/pal_ifaddrs.c b/src/libraries/Native/Unix/System.Native/pal_ifaddrs.c index 9ef4ca3abda4e..b49edd513280e 100644 --- a/src/libraries/Native/Unix/System.Native/pal_ifaddrs.c +++ b/src/libraries/Native/Unix/System.Native/pal_ifaddrs.c @@ -312,7 +312,7 @@ static struct ifaddrs *get_link_info(struct nlmsghdr *message) break; case IFLA_BROADCAST: - LOG_DEBUG(" interface broadcast (%lu bytes)\n", RTA_PAYLOAD(attribute)); + LOG_DEBUG(" interface broadcast (%zu bytes)\n", RTA_PAYLOAD(attribute)); if (fill_ll_address(&sa, net_interface, RTA_DATA(attribute), RTA_PAYLOAD(attribute)) < 0) { goto error; } @@ -320,7 +320,7 @@ static struct ifaddrs *get_link_info(struct nlmsghdr *message) break; case IFLA_ADDRESS: - LOG_DEBUG(" interface address (%lu bytes)\n", RTA_PAYLOAD(attribute)); + LOG_DEBUG(" interface address (%zu bytes)\n", RTA_PAYLOAD(attribute)); if (fill_ll_address(&sa, net_interface, RTA_DATA(attribute), RTA_PAYLOAD(attribute)) < 0) { goto error; } @@ -352,7 +352,7 @@ static struct ifaddrs *find_interface_by_index(int index, struct ifaddrs **ifadd return NULL; /* Normally expensive, but with the small amount of links in the chain we'll deal with it's not - * worth the extra houskeeping and memory overhead + * worth the extra housekeeping and memory overhead */ cur = *ifaddrs_head; while (cur) { @@ -509,7 +509,7 @@ static struct ifaddrs *get_link_address(struct nlmsghdr *message, struct ifaddrs LOG_DEBUG(" attribute type: LOCAL"); if (ifa->ifa_addr) { /* P2P protocol, set the dst/broadcast address union from the original address. - * Since ifa_addr is set it means IFA_ADDRESS occured earlier and that address + * Since ifa_addr is set it means IFA_ADDRESS occurred earlier and that address * is indeed the P2P destination one. */ ifa->ifa_dstaddr = ifa->ifa_addr; @@ -531,7 +531,7 @@ static struct ifaddrs *get_link_address(struct nlmsghdr *message, struct ifaddrs case IFA_ADDRESS: LOG_DEBUG(" attribute type: ADDRESS"); if (ifa->ifa_addr) { - /* Apparently IFA_LOCAL occured earlier and we have a P2P connection + /* Apparently IFA_LOCAL occurred earlier and we have a P2P connection * here. IFA_LOCAL carries the destination address, move it there */ ifa->ifa_dstaddr = ifa->ifa_addr; @@ -570,7 +570,7 @@ static struct ifaddrs *get_link_address(struct nlmsghdr *message, struct ifaddrs attribute = RTA_NEXT(attribute, length); } - /* glibc stores the associated interface name in the address if IFA_LABEL never occured */ + /* glibc stores the associated interface name in the address if IFA_LABEL never occurred */ if (!ifa->ifa_name) { char *name = get_interface_name_by_index((int)(net_address->ifa_index), ifaddrs_head); LOG_DEBUG(" address has no name/label, getting one from interface\n"); @@ -708,7 +708,7 @@ static int parse_netlink_reply(struct netlink_session *session, struct ifaddrs * return ret; } -int getifaddrs(struct ifaddrs **ifap) +int _netlink_getifaddrs(struct ifaddrs **ifap) { int ret = -1; @@ -728,7 +728,7 @@ int getifaddrs(struct ifaddrs **ifap) (parse_netlink_reply(&session, &ifaddrs_head, &last_ifaddr) < 0) || (send_netlink_dump_request(&session, RTM_GETADDR) < 0) || (parse_netlink_reply(&session, &ifaddrs_head, &last_ifaddr) < 0)) { - freeifaddrs (ifaddrs_head); + _netlink_freeifaddrs (ifaddrs_head); goto cleanup; } @@ -744,7 +744,7 @@ int getifaddrs(struct ifaddrs **ifap) return ret; } -void freeifaddrs(struct ifaddrs *ifa) +void _netlink_freeifaddrs(struct ifaddrs *ifa) { struct ifaddrs *cur, *next; diff --git a/src/libraries/Native/Unix/System.Native/pal_ifaddrs.h b/src/libraries/Native/Unix/System.Native/pal_ifaddrs.h index e52a392b13d9d..0944eeb43eb9f 100644 --- a/src/libraries/Native/Unix/System.Native/pal_ifaddrs.h +++ b/src/libraries/Native/Unix/System.Native/pal_ifaddrs.h @@ -7,37 +7,15 @@ #error The pal_ifaddrs.h shim is intended only for Android #endif +#if __ANDROID_API__ >= 24 +#error The pal_ifaddrs.h shim is only necessary for Android API 21-23 and it should be removed now that the minimum supported API level is 24 or higher +#endif + // Android doesn't include the getifaddrs and freeifaddrs functions in older Bionic libc (pre API 24). -// In recent Android versions (Android 11+) the data returned by the getifaddrs function is not valid. // This shim is a port of Xamarin Android's implementation of getifaddrs using Netlink. +// https://github.com/xamarin/xamarin-android/blob/681887ebdbd192ce7ce1cd02221d4939599ba762/src/monodroid/jni/xamarin_getifaddrs.h -#include "pal_compiler.h" -#include "pal_config.h" -#include "pal_types.h" - -#include -#include -#include - -struct ifaddrs -{ - struct ifaddrs *ifa_next; - char *ifa_name; - unsigned int ifa_flags; - struct sockaddr *ifa_addr; - struct sockaddr *ifa_netmask; - union - { - struct sockaddr *ifu_broadaddr; - struct sockaddr *ifu_dstaddr; - } ifa_ifu; - void *ifa_data; -}; - -// Synonym for `ifa_ifu.ifu_broadaddr` in `struct ifaddrs`. -#define ifa_broadaddr ifa_ifu.ifu_broadaddr -// Synonym for `ifa_ifu.ifu_dstaddr` in `struct ifaddrs`. -#define ifa_dstaddr ifa_ifu.ifu_dstaddr +#include -int getifaddrs (struct ifaddrs **ifap); -void freeifaddrs (struct ifaddrs *ifap); +int _netlink_getifaddrs (struct ifaddrs **ifap); +void _netlink_freeifaddrs (struct ifaddrs *ifap); diff --git a/src/libraries/Native/Unix/System.Native/pal_interfaceaddresses.c b/src/libraries/Native/Unix/System.Native/pal_interfaceaddresses.c index 0a92305bcbd48..506127d641156 100644 --- a/src/libraries/Native/Unix/System.Native/pal_interfaceaddresses.c +++ b/src/libraries/Native/Unix/System.Native/pal_interfaceaddresses.c @@ -17,6 +17,7 @@ #ifdef ANDROID_GETIFADDRS_WORKAROUND #include #include +#include "pal_ifaddrs.h" // fallback for Android API 21-23 #endif #include #include @@ -102,19 +103,30 @@ static inline uint8_t mask2prefix(uint8_t* mask, int length) } #ifdef ANDROID_GETIFADDRS_WORKAROUND -// Try to load the getifaddrs and freeifaddrs functions manually. -// This workaround is necessary on Android prior to API 24 and it can be removed once -// we drop support for earlier Android versions. +// This workaround is necessary as long as we support Android API 21-23 and it can be removed once +// we drop support for these old Android versions. static int (*getifaddrs)(struct ifaddrs**) = NULL; static void (*freeifaddrs)(struct ifaddrs*) = NULL; static void try_loading_getifaddrs() { - void *libc = dlopen("libc.so", RTLD_NOW); - if (libc) + if (android_get_device_api_level() >= 24) { - getifaddrs = (int (*)(struct ifaddrs**)) dlsym(libc, "getifaddrs"); - freeifaddrs = (void (*)(struct ifaddrs*)) dlsym(libc, "freeifaddrs"); + // Bionic on API 24+ contains the getifaddrs/freeifaddrs functions but the NDK doesn't expose those functions + // in ifaddrs.h when the minimum supported SDK is lower than 24 and therefore we need to load them manually + void *libc = dlopen("libc.so", RTLD_NOW); + if (libc) + { + getifaddrs = (int (*)(struct ifaddrs**)) dlsym(libc, "getifaddrs"); + freeifaddrs = (void (*)(struct ifaddrs*)) dlsym(libc, "freeifaddrs"); + } + } + else + { + // Bionic on API 21-23 doesn't contain the implementation of getifaddrs/freeifaddrs at all + // and we need to reimplement it using netlink (see pal_ifaddrs) + getifaddrs = _netlink_getifaddrs; + freeifaddrs = _netlink_freeifaddrs; } }