tech74 tech74 - 2 months ago 21
Linux Question

getaddrinfo on Android returning error EAI_BADFLAGS

We are trying to use getaddrinfo on Android API 14 and above ( in C++ code using NDK r12) to obtain synthesised IPV6 addresses from an IPV4 address. This is for use on IPV6 only networks with NAT64. However getaddrinfo returns EAI_BADFLAGS if aiflags is set (AI_V4MAPPED | AI_ADDRCONFIG).

struct addrinfo *ai, hints;
memset(&hints, 0, sizeof(hints));
hints.ai_socktype = SOCK_DGRAM;

hints.ai_flags = (AI_V4MAPPED | AI_ADDRCONFIG);
hints.ai_family = AF_UNSPEC;
int error = getaddrinfo( "46.23.43.12", "80", &hints, &ai);
if( error == 0)


Are there any major differences from Linux?

Answer

Yes, some differences to linux are expected. Even though Android runs on a Linux kernel, the libc, bionic, is pretty much based on BSD (some parts of it is from a pretty old version as well, although that has been brought up to date recently).

I'm not sure if there's any explicit documentation about this, but you can check the implementation to get an idea of how it probably behaves.

See lines 617-718 here: https://android.googlesource.com/platform/bionic/+/085543106/libc/dns/net/getaddrinfo.c

    if (hints->ai_flags & ~AI_MASK)
        ERR(EAI_BADFLAGS);

And lines 153-170 here: https://android.googlesource.com/platform/bionic/+/085543106/libc/include/netdb.h

/*
 * Flag values for getaddrinfo()
 */
#define AI_PASSIVE  0x00000001 /* get address to use bind() */
#define AI_CANONNAME    0x00000002 /* fill ai_canonname */
#define AI_NUMERICHOST  0x00000004 /* prevent host name resolution */
#define AI_NUMERICSERV  0x00000008 /* prevent service name resolution */
/* valid flags for addrinfo (not a standard def, apps should not use it) */
#define AI_MASK \
    (AI_PASSIVE | AI_CANONNAME | AI_NUMERICHOST | AI_NUMERICSERV | \
    AI_ADDRCONFIG)
#define AI_ALL      0x00000100 /* IPv6 and IPv4-mapped (with AI_V4MAPPED) */
#define AI_V4MAPPED_CFG 0x00000200 /* accept IPv4-mapped if kernel supports */
#define AI_ADDRCONFIG   0x00000400 /* only if any address is assigned */
#define AI_V4MAPPED 0x00000800 /* accept IPv4-mapped IPv6 address */
/* special recommended flags for getipnodebyname */
#define AI_DEFAULT  (AI_V4MAPPED_CFG | AI_ADDRCONFIG)

So getaddrinfo returns EAI_BADFLAGS if you set any flag outside of those listed in AI_MASK. Additionally, there's actually no use of AI_V4MAPPED anywhere within bionic, and only one mention of AI_ADDRCONFIG outside of comments (and it seems you can never actually reach it since getaddrinfo forbids setting it).

Comments