I know that sockaddr_in is for IPv4, and sockaddr_in6 for IPv6. The confusion to me is the difference between sockaddr and sockaddr_in[6].
Some functions accept
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.