getaddrinfo() fills struct addrinfo
where actual packed address stored in struct sockaddr *ai_addr
field. struct sockaddr
has field char *sa_data
with actual binary address representation. I want to copy this sa_data to another variable using memcpy()
, for this I need to know actual length of this field.
I thinked ai_addrlen is what I need. But in fact it returns 16 for IPv4 and 28 for IPv6. Too much I think. So, what is the most correct way to get sa_data length? May be length = sa_family == AF_INET ? 4 : 16
or length = ai_addrlen - 12
?
The getaddrinfo()
function returns a linked list consisting of struct addrinfo
records. Each of those records includes a pointer to struct sockaddr
which is a polymorphic type, behind which there is actually a struct sockaddr_in
or struct sockaddr_in6
. The ai_addrlen
member tells you how large is that structure, i.e. returns either sizeof (struct sockaddr_in)
or sizeof (struct sockaddr_in6)
.
Those structures contain the binary IP address, the port number (for the transport protocol like TCP or UDP), the family (repeated in struct addrinfo
as well) and other data (flowinfo and scope_id for IPv6, when looking at linux docs).
The actual binary address is inside the struct sockaddr_in
and strict sockaddr_in6
as struct in_addr sin_addr
and struct in6_addr sin6_addr
. You can use those fields or types to determine the size.
length = sa_family == AF_INET ? sizeof (struct in_addr) : sizeof (struct in6_addr)
As those are known numbers, you can of course use what you have already in your question.
length = sa_family == AF_INET ? 4 : 16
But you also tried to do arithmetics on ai_addrlen
and that is not a good idea, as the types can vary by operating system and there's no logic in that anyway. I can add more details if you had a specific use case or specific code.