linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* Problem with unix sockets: SOCK_DGRAM ignores MSG_TRUNC
@ 2007-01-29 11:59 Daniel Kabs
  2007-02-05  0:52 ` David Miller
  0 siblings, 1 reply; 6+ messages in thread
From: Daniel Kabs @ 2007-01-29 11:59 UTC (permalink / raw)
  To: linux-kernel

Hi,

I use unix domain datagram sockets for IPC, e.g. I receive messages by 
calling recv().

"man 2 recv" tells me about the flags argument to a recv() call, namely:

 MSG_TRUNC
      Return  the  real  length of the packet, even when it was longer
      than the passed buffer. Only valid for packet sockets.

Thus I used recv() with flags MSG_TRUNC|MSG_PEEK in order to detect 
message truncation due to insufficient buffer size.

Strangely enough, MSG_TRUNC seems to get ignored by the kernel: If the 
message received is larger than the receive buffer I supplied, the 
function returns the size of the buffer. I think, the function should 
return the real message length instead (at least according to the manual 
page).

To work around this problem, I now use the ioctl FIONREAD instead.

On the other hand, in this mailing list, I found an old bug report 
describing the same problem using UDP sockets:

http://groups.google.com/group/fa.linux.kernel/browse_frm/thread/fb6acbb527507e26/ad0b2ba33b6b66fa

UDP sockets seem to have been patched by now. From linux/net/ipv4/udp.c:
 udp_recvmsg()
  ...
        err = copied;
        if (flags & MSG_TRUNC)
                err = skb->len - sizeof(struct udphdr);
   ...

Why doesn't unix_dgram_recvmsg() in linux/net/unix/af_unix.c contain code 
to this effect? Is this a feature or a bug? What is the correct semantics 
of MSG_TRUNC when used for unix sockets?

Cheers
Daniel Kabs

PS: According to some lkml archives, my previous mail did not come 
through, so I reposted it.

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Problem with unix sockets: SOCK_DGRAM ignores MSG_TRUNC
  2007-01-29 11:59 Problem with unix sockets: SOCK_DGRAM ignores MSG_TRUNC Daniel Kabs
@ 2007-02-05  0:52 ` David Miller
  2007-02-06 12:55   ` Daniel Kabs
  2007-02-07  9:31   ` Daniel Kabs
  0 siblings, 2 replies; 6+ messages in thread
From: David Miller @ 2007-02-05  0:52 UTC (permalink / raw)
  To: dkabs; +Cc: linux-kernel

From: Daniel Kabs <dkabs@mobotix.com>
Date: Mon, 29 Jan 2007 12:59:49 +0100

> I use unix domain datagram sockets for IPC, e.g. I receive messages by 
> calling recv().
> 
> "man 2 recv" tells me about the flags argument to a recv() call, namely:
> 
>  MSG_TRUNC
>       Return  the  real  length of the packet, even when it was longer
>       than the passed buffer. Only valid for packet sockets.
> 
> Thus I used recv() with flags MSG_TRUNC|MSG_PEEK in order to detect 
> message truncation due to insufficient buffer size.

What part of "Only valid for packet sockets" from the manual page
escapes you?  :-))

It's a feature which only was meant to be valid for AF_PACKET sockets.

What UDP is doing is different, it's returning the full packet length
when the packet is larger then the given buffer size, but it does this
irregardless of whether you set MSG_TRUNC in the recvmsg() passed-in
flags.  UDP itself sets the MSG_TRUNC flag when it detects this
situation.

I checked the history and our AF_UNIX sockets have always behaved like
this.

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Problem with unix sockets: SOCK_DGRAM ignores MSG_TRUNC
  2007-02-05  0:52 ` David Miller
@ 2007-02-06 12:55   ` Daniel Kabs
  2007-02-06 20:11     ` David Schwartz
  2007-02-07  9:31   ` Daniel Kabs
  1 sibling, 1 reply; 6+ messages in thread
From: Daniel Kabs @ 2007-02-06 12:55 UTC (permalink / raw)
  To: David Miller; +Cc: linux-kernel

On Monday 05 February 2007 01:52, David Miller wrote:
> > Thus I used recv() with flags MSG_TRUNC|MSG_PEEK in order to detect
> > message truncation due to insufficient buffer size.
>
> What part of "Only valid for packet sockets" from the manual page
> escapes you?  :-))
> It's a feature which only was meant to be valid for AF_PACKET sockets.

Thanks for pointing that out. I thought, "packet sockets" means  
"datagram-oriented  socket". Obviously it means PF_PACKET instead. It's 
hard to learn programming IPC by only reading man pages :-)

> What UDP is doing is different, it's returning the full packet length
> when the packet is larger then the given buffer size, but it does this
> irregardless of whether you set MSG_TRUNC in the recvmsg() passed-in
> flags.  UDP itself sets the MSG_TRUNC flag when it detects this
> situation.

Please correct me gently if I am wrong: According to the kernel source 
code, this behaviour was introduced with patch-2.6.8: 

http://www.kernel.org/diff/diffview.cgi?file=/pub/linux/kernel/v2.6/patch-2.6.8.gz;z=4325

linux/net/ipv4/udp.c 
+
         err = copied;
+        if (flags & MSG_TRUNC)
+          err = skb->len - sizeof(struct udphdr);

I think local sockets (PF_UNIX) implement a different semantics: According 
to unix_dgram_recvmsg() in linux/net/unix/af_unix.c, in case of 
truncation the buffer size is returned and not the full packet length.

In my opinion this implementation of local sockets (PF_UNIX) is not 
following the wording of the man page man 2 recv: "These  calls  return  
the  number of bytes received". Am I getting something wrong here?

Why not improve consistency and make unix_dgram_recvmsg() return the full 
packet length? So it would behave as UDP does. What do you think about 
adding the following code to linux/net/unix/af_unix.c:
        err = size;
+        if (flags & MSG_TRUNC)
+                err = skb->len;


Cheers
Daniel

^ permalink raw reply	[flat|nested] 6+ messages in thread

* RE: Problem with unix sockets: SOCK_DGRAM ignores MSG_TRUNC
  2007-02-06 12:55   ` Daniel Kabs
@ 2007-02-06 20:11     ` David Schwartz
  2007-02-07  8:58       ` Daniel Kabs
  0 siblings, 1 reply; 6+ messages in thread
From: David Schwartz @ 2007-02-06 20:11 UTC (permalink / raw)
  To: Linux-Kernel@Vger. Kernel. Org


> Why not improve consistency and make unix_dgram_recvmsg() return the full
> packet length? So it would behave as UDP does. What do you think about
> adding the following code to linux/net/unix/af_unix.c:

It would be nice if the world worked that way, but you can't break POSIX
compliance. Perhaps another receive flag?

DS



^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Problem with unix sockets: SOCK_DGRAM ignores MSG_TRUNC
  2007-02-06 20:11     ` David Schwartz
@ 2007-02-07  8:58       ` Daniel Kabs
  0 siblings, 0 replies; 6+ messages in thread
From: Daniel Kabs @ 2007-02-07  8:58 UTC (permalink / raw)
  To: davids; +Cc: Linux-Kernel@Vger. Kernel. Org

On Tuesday 06 February 2007 21:11, David Schwartz wrote:
> > Why not improve consistency and make unix_dgram_recvmsg() return the
> > full packet length? So it would behave as UDP does. What do you think
> > about adding the following code to linux/net/unix/af_unix.c:
>
> It would be nice if the world worked that way, but you can't break
> POSIX compliance. Perhaps another receive flag?

I now understand that setting the MSG_TRUNC flag is only applicable for 
PF_PACKET. I do not argue about that any more. :-)

What I question is the return value when receiving from a local socket 
using recv(). Sorry, I don't know what the POSIX standard has to say 
about receiving from local sockets in contrast to UDP sockets as my only 
reference are the man pages.

According to "man 2 recv", on success the return value is the "the  number  
of bytes received". Since patch-2.6.8, UDP is always returning the full 
packet length. I'd like to see local sockets (PF_UNIX) to do the same. 

Does POSIX stipulate a different behaviour for local sockets?

Cheers
Daniel

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Problem with unix sockets: SOCK_DGRAM ignores MSG_TRUNC
  2007-02-05  0:52 ` David Miller
  2007-02-06 12:55   ` Daniel Kabs
@ 2007-02-07  9:31   ` Daniel Kabs
  1 sibling, 0 replies; 6+ messages in thread
From: Daniel Kabs @ 2007-02-07  9:31 UTC (permalink / raw)
  To: David Miller; +Cc: linux-kernel

On Monday 05 February 2007 01:52, David Miller wrote:
> What UDP is doing is different, it's returning the full packet length
> when the packet is larger then the given buffer size, but it does this
> irregardless of whether you set MSG_TRUNC in the recvmsg() passed-in
> flags.  UDP itself sets the MSG_TRUNC flag when it detects this
> situation.

I hope that I am researching the appropriate kernel source tree, but if I 
am not mistaken, this behaviour was introduced with change 1.66 according 
to bitkeeper:
  http://linux.bkbits.net:8080/linux-2.6/net/ipv4/udp.c?PAGE=history

I think the bitkeeper comment on that change (1.66) is misleading:
  "[UDP]: Return true length if user specifies MSG_TRUNC."

As you said, this is wrong. The true length is returned, regardless 
whether the user specified MSG_TRUNC.

Exploring this topic I learned a lot about browsing and reading kernel 
source code, e.g. that commit statements have to be taken with a grain of 
salt :-)

Cheers
Daniel

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2007-02-07  9:32 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2007-01-29 11:59 Problem with unix sockets: SOCK_DGRAM ignores MSG_TRUNC Daniel Kabs
2007-02-05  0:52 ` David Miller
2007-02-06 12:55   ` Daniel Kabs
2007-02-06 20:11     ` David Schwartz
2007-02-07  8:58       ` Daniel Kabs
2007-02-07  9:31   ` Daniel Kabs

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).