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.

  • 1
    There some discussion here.
    – meuh
    Feb 9, 2021 at 16:21
  • @meuh Thank you! That wasn't exactly what I was looking for, as in that case they are using recvmsg() to receive all messages, which would be able to take file descriptors, rather than recv(), which wouldn't, but it was indeed enlightening.
    – novice
    Feb 10, 2021 at 1:18
  • 2
    I will try to make an answer when I have time but tl;dr; 1. a read(), recv(), recvfrom(), recvmsg() can receive the data written by a sendmsg() -- no need to "pair" a sendmsg() with a recvmsg(). A single read(), recv(), etc can even receive the data written by multiple sendmsg() -- if it's a stream socket, but 2. a single recvmsg(), 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).
    – user313992
    Feb 10, 2021 at 1:23


You must log in to answer this question.

Browse other questions tagged .