A struct sockaddr
should generally only be used as the base type for a pointer. It is a structure intended to cover the common initial sequence of the members in the address family specific socket address types (struct sockaddr_un
, struct sockaddr_in
, struct sockaddr_in6
etc.)
The only member that you can rely on struct sockaddr
having is a single sa_family_t
, indicating the socket address family. The idea is that to obtain a sort of polymorphism - you can have a function that can operate on several different socket address types:
void foo(struct sockaddr *sa)
{
switch(sa->sa_family)
{
case AF_INET: {
struct sockaddr_in *sa_in = (struct sockaddr_in *)sa;
/* AF_INET processing */
}
case AF_UNIX: {
struct sockaddr_un *sa_un = (struct sockaddr_un *)sa;
/* AF_UNIX processing */
}
/* ... */
Note though that code like the above is generally considered to break the "strict aliasing" rule in C - if you want to do that in your own code, you are supposed to use a union type:
union sockaddr {
struct sockaddr sa;
struct sockaddr_in sin;
struct sockaddr_un sun;
/* ... */
};
void foo(union sockaddr *sa_union)
{
struct sockaddr *sa = (struct sockaddr *)sa_union;
switch(sa->sa_family)
{
case AF_INET: {
struct sockaddr_in *sa_in = (struct sockaddr_in *)sa;
/* AF_INET processing */
}
case AF_UNIX: {
struct sockaddr_un *sa_un = (struct sockaddr_un *)sa;
/* AF_UNIX processing */
}
/* ... */