I am doing some interposition in Mac OS X (essentially intercepting C calls) and I noticed that the ping application tries to call the sendto function with an addrlen value of 16. In sys/socket.h I can see clearly that the sa_data array only holds up to 14 bytes:
/*
* [XSI] Structure used by kernel to store most addresses.
*/
struct sockaddr {
__uint8_t sa_len; /* total length */
sa_family_t sa_family; /* [XSI] address family */
char sa_data[14]; /* [XSI] addr value (actually larger) */
};
It freaks me out that the comment says "actually larger" but there's not much I can do about that.
Anyway, the man page shows the signature for the sendto function looks like this:
ssize_t
sendto(int socket,
const void *buffer,
size_t length,
int flags,
const struct sockaddr *dest_addr,
socklen_t dest_len);
And then the man page specifically calls out what to do if the length value is too long for a message to be delivered atomically. It ignores the situation where dest_len is larger than what dest_addr.sa_data can hold.
If I try to copy 16 bytes of data into another dest_addr.sa_data from the caller it fails and the application crashes, as it should. Am I misunderstanding how this field is used? Why does the comment in the header say "actually larger" but then assigns a fixed size to the array?
You never actually are supposed to use struct sockaddr
. It's like void
in void *
, a stand-in for the actual sockaddr_foo
structures.