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>