[prev in list] [next in list] [prev in thread] [next in thread] 

List:       freebsd-hackers
Subject:    Re: Interpretation of POSIX.1-2008 for recvmsg
From:       Marcin Cieslak <saper () saper ! info>
Date:       2015-07-31 23:59:00
Message-ID: alpine.BSF.2.11.1507312335080.7491 () z ! fncre ! vasb
[Download RAW message or body]

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

_______________________________________________
freebsd-hackers@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-hackers
To unsubscribe, send any mail to "freebsd-hackers-unsubscribe@freebsd.org"


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic