I am aware of this similar question, but the answers do not make sense and are possibly for a different problem.
In my iOS app I connect to a server using CFSockets and wish to show the remote address of the server. When using IPv4 it works as expected, but there are weird results with IPv6 where the network prefix of the address are correct, but the host bits are completely different.
int sock_fd = <...> // Assume I already have the fd
struct sockaddr addr;
socklen_t addr_len = sizeof(addr);
getpeername(sock_fd, &addr, &addr_len);
char addressString[INET6_ADDRSTRLEN];
inet_ntop(AF_INET6, &((struct sockaddr_in6 *)&addr)->sin6_addr, addressString, INET6_ADDRSTRLEN);
What I expected was 2607:f2f8:a4c8::2
but what I get is an address with the correct network prefix but different host bits each time, e.g:
vvvvvvvvvvvvvvvvvvvv Random?
2607:f2f8:a4c8:0:c400:13b0:f6c5:afa
^^^^^^^^^^^^^^ Correct
The man page of getpeername(2)
gives a hint as to why this is happening:
The address_len parameter should be initialized to indicate the amount of space pointed to by address. On return it contains the actual size of the address returned (in bytes).
The address is truncated if the buffer provided is too small.
The size of struct sockaddr
is too small for IPv6 addresses and will result in the address being truncated.
You need to use struct sockaddr_storage
with getpeername
rather than just struct sockaddr
struct sockaddr_storage addr;
socklen_t addr_len = sizeof(addr);
getpeername(socket, (struct sockaddr *)&addr, &addr_len)