I wanted to add IPv6 support for my program and came across odd error. I want to open socket which accepts connections. Here is my scenario:
First I use getaddrinfo() to find socket configuration:
struct addrinfo hint, *info = NULL;
memset((void *)&hint, 0, sizeof(hint));
hint.ai_family = AF_INET6;
hint.ai_flags = AI_PASSIVE | AI_NUMERICSERV;
hint.ai_socktype = SOCK_STREAM;
if ((error = getaddrinfo(NULL, "1234", &hint, &info))) {
/* some error handling */
}
I gen non-NULL result in info
. Then I want to create socket:
socket(info->ai_family, info->ai_socktype, info->ai_protocol)
Here I get -1
strerror(errno)
returns Address family not supported by protocol
I thought that getaddrinfo()
returns only addresses that can be bound and I would expect it to return NULL in this case. What am I missing?
I want to add that my eth0 does not have IPv6 address right now. I am using uClibc 0.9.32
You need to add AI_ADDRCONFIG
to ai_flags to make sure it doesn't return address families unsupported by the kernel. I pretty much always add that flag nowadays.
If you want to support kernels without IPv6 you'll have to avoid setting ai_family to AF_INET6. Instead you have to listen on all the returned addresses, and make sure to set IPV6_V6ONLY on the AF_INET6 ones. There's no guarantee that the AF_INET6 address will be returned first, unfortunately.