Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 31 Jul 2015 23:59:00 +0000
From:      Marcin Cieslak <saper@saper.info>
To:        Patrick Mooney <patrick.mooney@joyent.com>
Cc:        freebsd-hackers@freebsd.org
Subject:   Re: Interpretation of POSIX.1-2008 for recvmsg
Message-ID:  <alpine.BSF.2.11.1507312335080.7491@z.fncre.vasb>
In-Reply-To: <CABtm=mocvtBO46PDR7SPokOr57z_DphOu5rKZPk7ATjweL_Awg@mail.gmail.com>
References:  <CABtm=mocvtBO46PDR7SPokOr57z_DphOu5rKZPk7ATjweL_Awg@mail.gmail.com>

next in thread | previous in thread | raw e-mail | index | archive | help
On Fri, 31 Jul 2015, Patrick Mooney wrote:

> Greetings,
> I have been researching differences in recvmsg() behavior across platforms
> (namely Illumos and Linux) with respect to MSG_PEEK and 0-length buffers.
> Certain Linux software I am attempting to run under Illumos makes a recvmsg()
> call with a 0-length iovec and flags set to MSG_PEEK in order to interrogate
> the size of a queued dgram.  On native Linux, recvmsg() returns the size of the
> queued dgram (with the MSG_TRUNC flag set).  On both Illumos and FreeBSD, a
> size of 0 is returned (with MSG_TRUNC set as well).  In reading the POSIX spec
> (http://pubs.opengroup.org/onlinepubs/9699919799/functions/recvmsg.html), it is
> not clear that returning 0 in this case is correct behavior.
> 
> Here is a small test program I wrote up to display the differences in behavior:
> https://us-east.manta.joyent.com/patrick.mooney/public/recvmsg/peektest.c
> 
> The output on Linux:
> peek len: 20 errno: 0 flags: 20
> recv len: 20 errno: 0 flags: 0
> ... versus BSD and Illumos:

> peek len: 0 errno: 2 flags: 12
> recv len: 20 errno: 2 flags: 0

errno does not has to be reset to 0 to indicate
success. You should check return value < 0 before using errno.
I set errno to 0 before invoking recvmsg() and
it stays 0 (that means it is just not modified).

Also setting MSG_TRUNC in the input flags is not specified
by POSIX (use just MSG_PEEK). MSG_TRUNC is the output flag.
What you are expecting is the non-standard Linux
behaviour with this flag set as input:

       MSG_TRUNC (since Linux 2.2)
              For  raw  (AF_PACKET), Internet datagram (since Linux 2.4.27/2.6.8), netlink (since Linux 2.6.22) and UNIX datagram (since Linux
              3.4) sockets: return the real length of the packet or datagram, even when it was longer than the passed buffer.  Not implemented
              for UNIX domain (unix(7)) sockets.

Be aware that recvmsg(x, y, MSG_PEEK) *also* reads data -
so Solaris and BSD consitently return what was saved
into the buffer.

In short - to check how large the message is, supply the buffer
that is large enough (or try MSG_PEEK until it is large enough).

Here are the result of my modified peektest.c[1]:

peek buflen: 0x02
peek len: 0x02 errno: 0 flags: 0x12
peek read: [AB  ]
read buflen: 0x20
recv len: 0x20 errno: 0 flags: 0x00
recv read: [ABCD]

On Linux:

Using port 18399
peek buflen: 0x02
peek len: 0x02 errno: 0 flags: 0x20
peek read: [AB  ]
read buflen: 0x20
recv len: 0x20 errno: 0 flags: 0x00
recv read: [ABCD]

MSG_TRUNC in the input flags is not POSIX.

//Marcin




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?alpine.BSF.2.11.1507312335080.7491>