The function prototype for the sendmsg() function is as follows:
ssize_t sendmsg(int sockfd, const struct msghdr *msg, int flags);
and the msghdr struct is such:
struct msghdr {
void *msg_name; /* optional address */
socklen_t msg_namelen; /* size of address */
struct iovec *msg_iov; /* scatter/gather array */
size_t msg_iovlen; /* # elements in msg_iov */
void *msg_control; /* ancillary data, see below */
size_t msg_controllen; /* ancillary data buffer len */
int msg_flags; /* flags on received message */
};
If I send a message over a UNIX domain socket with sendmsg()
containing both ancillary data in msg_control
(such as a file descriptor with SCM_RIGHTS) and regular message data in msg_iov
, will I be able to read the regular data in msg_iov
from that message at the other end of the socket with a call to recv()
, or will I only be able to get that data with a call to recvmsg()
? Put another way, are there effectively two different channels for a socket, one for sendmsg()
/recvmsg()
and another for send()
/recv()
, or are the two streams of regular message data mixed together?
If not, is it possible for a process to violate the association between a message and its ancillary data by reading forward multiple headers of regular message data without receiving its ancillary data and then only afterwards calling recvmsg()
to get the ancillary data of multiple previous messages, going out of order?
If a Message A with ancillary data is sent with sendmsg()
and then a Message B without ancillary data is sent with send()
, will I be prevented from receiving Message B with recv()
until I have received Message A with recvmsg()
?
I apologize if I fundamentally misunderstood any of underlying mechanisms of UNIX domain sockets. If I have, I would highly appreciate if someone could point out the false assumptions I have made.
read()
,recv()
,recvfrom()
,recvmsg()
can receive the data written by asendmsg()
-- no need to "pair" asendmsg()
with arecvmsg()
. A singleread()
,recv()
, etc can even receive the data written by multiplesendmsg()
-- if it's a stream socket, but 2. a singlerecvmsg()
,read()
will NOT (AFAIK) receive a mix of file descriptors, real credentials or chunks of data sent by different processes or the same process before and after changing its credentials (as when executing a setuid binary).