What's the difference between sockaddr, sockaddr_in, and sockaddr_in6?

sockaddr_in and sockaddr_in6 are both structures where first member is a sockaddr structure.

According to the C standard, the address of a structure and its first member are the same, so you can cast the pointer to sockaddr_in(6) in a pointer to sockaddr.

Functions taking sockaddr_in(6) as parameter may modify the sockaddr part, and functions taking sockaddr as parameter just care about that part.

It's a bit like inheritance.


I don't want to answer my question. But to give more information here which might be useful to other people, I decide to answer my question.

After dig into the source code of linux. Following is my finding, there are possible multiple protocol which all implement the getsockname. And each have themself underling address data structure, for example, for IPv4 it is sockaddr_in, and IPV6 sockaddr_in6, and sockaddr_un for AF_UNIX socket. sockaddr are used as the common data strut in the signature of those APIs.

Those API will copy the socketaddr_in or sockaddr_in6 or sockaddr_un to sockaddr base on another parameter length by memcpy.

And all of the data structure begin with same type field sa_family.

Base on those reason, the code snippet is valid, because both sockaddr_in and sockaddr_in6 have sa_family and then we can cast it to the correct data structure for usage after check sa_family.

BTY, I'm not sure why the sizeof(sockaddr_in6) > sizeof(sockaddr), which cause allocate memory base on size of sockaddr is not enough for ipv6( that is error-prone), but I guess it is because of history reason.