Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the purpose of the sa_data field in a sockaddr?

int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

The actual structure passed for the addr argument will depend on the address family. The sockaddr structure is defined as something like:

struct sockaddr {
    sa_family_t sa_family;
    char        sa_data[14];
}

So for an IPv4 address (AF_INET), the actual struct that will be passed is this:

/* Source http://linux.die.net/man/7/ip */

struct sockaddr_in {
    sa_family_t    sin_family; /* address family: AF_INET */
    in_port_t      sin_port;   /* port in network byte order */
    struct in_addr sin_addr;   /* internet address */
};

/* Internet address. */
struct in_addr {
    uint32_t       s_addr;     /* address in network byte order */
};

Does the bind code read the sockaddr.sa_family value and depending on the value it finds, it will then cast the sockaddr struct into the appropriate struct such as sockaddr_in?

Why is the sa_data set to 14 characters? If I understand correct, the sa_data field is just a field that will have large enough memory space to fit all address family types? Presumably the original designers anticipated that 14 characters would be wide enough to fit all future types.

like image 761
Chris Snow Avatar asked Sep 17 '15 07:09

Chris Snow


People also ask

What is Sa_family?

short int sa_family. This is the code for the address format of this address. It identifies the format of the data which follows. char sa_data[14] This is the actual socket address data, which is format-dependent.

What is Sockaddr?

sockaddr is used as the base of a set of address structures that act like a discriminated union, see the Beej guide to networking. You generally look at the sa_family and then cast to the appropriate address family's specific address structure.


1 Answers

According to the glibc manual:

The length 14 of sa_data is essentially arbitrary.

And the FreeBSD developers handbook mentions the following:

Please note the vagueness with which the sa_data field is declared, just as an array of 14 bytes, with the comment hinting there can be more than 14 of them.

This vagueness is quite deliberate. Sockets is a very powerful interface. While most people perhaps think of it as nothing more than the Internet interface—and most applications probably use it for that nowadays—sockets can be used for just about any kind of interprocess communications, of which the Internet (or, more precisely, IP) is only one.

Yes, the sa_family field is used to recognize how to treat the struct passed (which is cast to struct sockaddr* in a call to bind). You can read more about how it works also in a FreeBSD developers handbook.

And actually there are "polymorphic" (sub)types of sockaddr, in which sa_data contains more than 16 bytes, for example:

struct sockaddr_un {
    sa_family_t sun_family;               /* AF_UNIX */
    char        sun_path[108];            /* pathname */
};
like image 130
syntagma Avatar answered Sep 18 '22 07:09

syntagma