I don't understand why getaddrinfo is not returning a valid IPv6 address.
On my system the code below is printing 22:B8:00:00:00:00:00:00:00:00:00:00:00:00, but I expected a 01 somewhere, since localhost should resolve to ::1.
At the same time, sa_data is only 14 bytes, whereas IPv6 addresses are 16 bytes, so it seems that the last couple of bytes are always chopped off, and the function can't return an IPv6 address?
Can someone explain what's going on? How am I supposed to use this function with IPv6?
#include <stdio.h>
#include <WinSock2.h>
#include <WS2TCPIP.h>
#pragma comment(lib, "WS2_32")
int main(int argc, char *argv[])
{
WSADATA wsadata;
WSAStartup(0x0002, &wsadata);
addrinfo addr_hints = { 0, PF_INET6, SOCK_DGRAM, IPPROTO_UDP }, *addrs_out;
getaddrinfo("localhost", "8888", &addr_hints, &addrs_out);
fprintf(stderr,
"%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n",
static_cast<unsigned char>(addrs_out->ai_addr->sa_data[ 0]),
static_cast<unsigned char>(addrs_out->ai_addr->sa_data[ 1]),
static_cast<unsigned char>(addrs_out->ai_addr->sa_data[ 2]),
static_cast<unsigned char>(addrs_out->ai_addr->sa_data[ 3]),
static_cast<unsigned char>(addrs_out->ai_addr->sa_data[ 4]),
static_cast<unsigned char>(addrs_out->ai_addr->sa_data[ 5]),
static_cast<unsigned char>(addrs_out->ai_addr->sa_data[ 6]),
static_cast<unsigned char>(addrs_out->ai_addr->sa_data[ 7]),
static_cast<unsigned char>(addrs_out->ai_addr->sa_data[ 8]),
static_cast<unsigned char>(addrs_out->ai_addr->sa_data[ 9]),
static_cast<unsigned char>(addrs_out->ai_addr->sa_data[10]),
static_cast<unsigned char>(addrs_out->ai_addr->sa_data[11]),
static_cast<unsigned char>(addrs_out->ai_addr->sa_data[12]),
static_cast<unsigned char>(addrs_out->ai_addr->sa_data[13]));
freeaddrinfo(addrs_out);
return 0;
}
sockaddrstruct definitions for reference:When
ai_family == AF_INET6ai_addractually points to astruct sockaddr_in6. The first few bytes you are printing aresin6_portandsin6_flowinfo. The IPv6 address comes after.Edit to add:
You can use
ai_addrdirectly with functions likebind()andgetnameinfo(). You typically won't need to dig down into the struct definition details. For example, I would usegetnameinfo()withNI_NUMERICHOSTto get a printable address.