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;
}
sockaddr
struct definitions for reference:When
ai_family == AF_INET6
ai_addr
actually points to astruct sockaddr_in6
. The first few bytes you are printing aresin6_port
andsin6_flowinfo
. The IPv6 address comes after.Edit to add:
You can use
ai_addr
directly with functions likebind()
andgetnameinfo()
. You typically won't need to dig down into the struct definition details. For example, I would usegetnameinfo()
withNI_NUMERICHOST
to get a printable address.