public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH] sctp: implement SIOCINQ ioctl()
@ 2010-06-23 21:37 Diego Elio 'Flameeyes' Pettenò
  2010-06-24 13:19 ` Vlad Yasevich
  0 siblings, 1 reply; 6+ messages in thread
From: Diego Elio 'Flameeyes' Pettenò @ 2010-06-23 21:37 UTC (permalink / raw)
  To: linux-kernel, linux-sctp

This simple patch copies the current approach for SIOCINQ ioctl() from DCCP
into SCTp so that the userland code working with SCTP can use a similar
interface across different protocols to know how much space to allocate for
a buffer.
---
 net/sctp/socket.c |   31 ++++++++++++++++++++++++++++++-
 1 files changed, 30 insertions(+), 1 deletions(-)

diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index 44a1ab0..3135b4e 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -3595,7 +3595,36 @@ out:
 /* The SCTP ioctl handler. */
 SCTP_STATIC int sctp_ioctl(struct sock *sk, int cmd, unsigned long arg)
 {
-	return -ENOIOCTLCMD;
+	int rc = -ENOTCONN;
+
+	sctp_lock_sock(sk);
+
+	if (sctp_sstate(sk, LISTENING))
+		goto out;
+
+	switch(cmd) {
+	case SIOCINQ: {
+		struct sk_buff *skb;
+		unsigned long amount = 0;
+
+		skb = skb_peek(&sk->sk_receive_queue);
+		if (skb != NULL) {
+			/*
+			 * We will only return the amount of this packet since
+			 * that is all that will be read.
+			 */
+			amount = skb->len;
+		}
+		rc = put_user(amount, (int __user *)arg);
+	}
+		break;
+	default:
+		rc = -ENOIOCTLCMD;
+		break;
+	}
+out:
+	sctp_release_sock(sk);
+	return rc;
 }
 
 /* This is the function which gets called during socket creation to
-- 
1.7.1


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

* Re: [PATCH] sctp: implement SIOCINQ ioctl()
  2010-06-23 21:37 [PATCH] sctp: implement SIOCINQ ioctl() Diego Elio 'Flameeyes' Pettenò
@ 2010-06-24 13:19 ` Vlad Yasevich
  2010-06-24 13:20   ` Diego Elio “Flameeyes” Pettenò
  0 siblings, 1 reply; 6+ messages in thread
From: Vlad Yasevich @ 2010-06-24 13:19 UTC (permalink / raw)
  To: Diego Elio 'Flameeyes' Pettenò; +Cc: linux-kernel, linux-sctp



Diego Elio 'Flameeyes' Pettenò wrote:
> This simple patch copies the current approach for SIOCINQ ioctl() from DCCP
> into SCTp so that the userland code working with SCTP can use a similar
> interface across different protocols to know how much space to allocate for
> a buffer.
> ---
>  net/sctp/socket.c |   31 ++++++++++++++++++++++++++++++-
>  1 files changed, 30 insertions(+), 1 deletions(-)
> 
> diff --git a/net/sctp/socket.c b/net/sctp/socket.c
> index 44a1ab0..3135b4e 100644
> --- a/net/sctp/socket.c
> +++ b/net/sctp/socket.c
> @@ -3595,7 +3595,36 @@ out:
>  /* The SCTP ioctl handler. */
>  SCTP_STATIC int sctp_ioctl(struct sock *sk, int cmd, unsigned long arg)
>  {
> -	return -ENOIOCTLCMD;
> +	int rc = -ENOTCONN;
> +
> +	sctp_lock_sock(sk);
> +
> +	if (sctp_sstate(sk, LISTENING))

This should add a check for sctp_style(sk, TCP), since one can't read from
a TCP style listening sockets, but can do so from UDP-style (SOCK_SEQPACKET).

-vlad

> +		goto out;
> +
> +	switch(cmd) {
> +	case SIOCINQ: {
> +		struct sk_buff *skb;
> +		unsigned long amount = 0;
> +
> +		skb = skb_peek(&sk->sk_receive_queue);
> +		if (skb != NULL) {
> +			/*
> +			 * We will only return the amount of this packet since
> +			 * that is all that will be read.
> +			 */
> +			amount = skb->len;
> +		}
> +		rc = put_user(amount, (int __user *)arg);
> +	}
> +		break;
> +	default:
> +		rc = -ENOIOCTLCMD;
> +		break;
> +	}
> +out:
> +	sctp_release_sock(sk);
> +	return rc;
>  }
>  
>  /* This is the function which gets called during socket creation to

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

* Re: [PATCH] sctp: implement SIOCINQ ioctl()
  2010-06-24 13:19 ` Vlad Yasevich
@ 2010-06-24 13:20   ` Diego Elio “Flameeyes” Pettenò
  2010-06-24 13:40     ` Vlad Yasevich
  0 siblings, 1 reply; 6+ messages in thread
From: Diego Elio “Flameeyes” Pettenò @ 2010-06-24 13:20 UTC (permalink / raw)
  To: Vlad Yasevich; +Cc: linux-kernel, linux-sctp

[-- Attachment #1: Type: text/plain, Size: 1022 bytes --]

Il giorno gio, 24/06/2010 alle 09.19 -0400, Vlad Yasevich ha scritto:
> 
> This should add a check for sctp_style(sk, TCP), since one can't read
> from
> a TCP style listening sockets, but can do so from UDP-style
> (SOCK_SEQPACKET). 

I don't want to sound arrogant but... are you sure?

I ask because the simple testcase I wrote to make sure I didn't get it
wrong opened the socket as SOCK_STREAM, and yet all of this worked fine
(I'm attaching the source, for the sake of it)...

I sure hope you're mistaken here and it is _supposed_ to work here as
well, as we cannot use SOCK_SEQPACKET in the software I'm writing this
for (feng, from the lscube project) as accept() fails on SOCK_SEQPACKET
(EOPNOTSUPP) -- which itslef is strange given that the man page for
accept(2) reports it's supported on SOCK_STREAM and SOCK_SEQPACKET.

-- 
Diego Elio Pettenò — “Flameeyes”
http://blog.flameeyes.eu/

If you found a .asc file in this mail and know not what it is,
it's a GnuPG digital signature: http://www.gnupg.org/


[-- Attachment #2: sctp-fionread.c --]
[-- Type: text/x-csrc, Size: 2096 bytes --]

#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <linux/sockios.h>
#include <netinet/in.h>
#include <netinet/sctp.h>
#include <stdio.h>
#include <netdb.h>
#include <stdlib.h>

int main() {
  int sock, client, pkgsize, realpkgsize, i;
  uint8_t *pkg;
  struct addrinfo *res;

  static const struct addrinfo hints_ipv6 = {
    .ai_family = AF_INET,
    .ai_socktype = SOCK_SEQPACKET,
    .ai_flags = AI_PASSIVE
  };

  static const struct sctp_initmsg initparams = {
    .sinit_max_instreams = 5,
    .sinit_num_ostreams = 5,
  };

  static const struct sctp_event_subscribe subscribe = {
    .sctp_data_io_event = 1
  };

  static const int on = 1;

  if ( getaddrinfo(NULL, "2811", &hints_ipv6, &res) < 0 ) {
    perror("getaddrinfo");
    return -1;
  }

  if ( (sock = socket(res->ai_family, SOCK_STREAM, IPPROTO_SCTP)) < 0 ) {
    perror("socket");
    return -1;
  }
 
  if (setsockopt(sock, SOL_SCTP, SCTP_EVENTS, &subscribe,
		 sizeof(subscribe)) < 0) {
    perror("setsockopt(SCTP_EVENTS)");
    return -1;
  }

  if (setsockopt(sock, SOL_SCTP, SCTP_INITMSG, &initparams,
		 sizeof(initparams)) < 0) {
    perror("setsockopt(SCTP_INITMSG)");
    return -1;
  }

  if ( setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
		  &on, sizeof(on)) < 0 ) {
    perror("setsockopt(SO_REUSEADDR)");
    return -1;
  }

  if ( bind(sock, res->ai_addr, res->ai_addrlen) < 0 ) {
    perror("bind");
    return -1;
  }

  if ( listen(sock, 1) < 0 ) {
    perror("listen");
    return -1;
  }

  if ( (client = accept(sock, NULL, NULL)) < 0 ) {
    perror("accept");
    return -1;
  }

  sleep(10);

  if ( ioctl(client, SIOCINQ, &pkgsize) < 0 ) {
    perror("ioctl");
    return -1;
  }

  fprintf(stderr, "Expecting packet of size %d\n", pkgsize);

  pkg = malloc(pkgsize*2);
  realpkgsize = sctp_recvmsg(client,
			     pkg, pkgsize*2,
			     NULL, 0, NULL, NULL);

  fprintf(stderr, "Received packet of size %d\n", realpkgsize);

  for(i = 0; i < realpkgsize; i++)
    fprintf(stderr, "%02x ", pkg[i]);

  fprintf(stderr, "\n");

  close(client);
  close(sock);
  return 0;
}

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

* Re: [PATCH] sctp: implement SIOCINQ ioctl()
  2010-06-24 13:20   ` Diego Elio “Flameeyes” Pettenò
@ 2010-06-24 13:40     ` Vlad Yasevich
  2010-06-24 13:44       ` Diego Elio “Flameeyes” Pettenò
  0 siblings, 1 reply; 6+ messages in thread
From: Vlad Yasevich @ 2010-06-24 13:40 UTC (permalink / raw)
  To: Diego Elio “Flameeyes” Pettenò; +Cc: linux-kernel, linux-sctp



Diego Elio “Flameeyes” Pettenò wrote:
> Il giorno gio, 24/06/2010 alle 09.19 -0400, Vlad Yasevich ha scritto:
>> This should add a check for sctp_style(sk, TCP), since one can't read
>> from
>> a TCP style listening sockets, but can do so from UDP-style
>> (SOCK_SEQPACKET). 
> 
> I don't want to sound arrogant but... are you sure?

Yes, I am sure. :)

> 
> I ask because the simple testcase I wrote to make sure I didn't get it
> wrong opened the socket as SOCK_STREAM, and yet all of this worked fine
> (I'm attaching the source, for the sake of it)...
> 
> I sure hope you're mistaken here and it is _supposed_ to work here as
> well, as we cannot use SOCK_SEQPACKET in the software I'm writing this
> for (feng, from the lscube project) as accept() fails on SOCK_SEQPACKET
> (EOPNOTSUPP) -- which itslef is strange given that the man page for
> accept(2) reports it's supported on SOCK_STREAM and SOCK_SEQPACKET.
> 

You don't call accept() on an SCTP SEQPACKET socket.  You can just read from it.
SCTP uses SOCK_SEQPACKET to implement 1-to-many semantics, where you can have
multiple associations all serviced by the same socket.  In that case, the socket
is placed into the listening state and then the application may simply read
from it.

Thus your code that just returns the size of the first skb should take that into
consideration.

So the condition really is:
  if (sctp_style(sk, TCP) && sctp_state(sk, LISTENING))
	goto out;

This way, you'll ignore listening SOCK_STREAM sockets which will not have any
data anyway, but you'll check out listening SOCK_SEQPACKET sockets that may have
data waiting on them.

-vlad

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

* Re: [PATCH] sctp: implement SIOCINQ ioctl()
  2010-06-24 13:40     ` Vlad Yasevich
@ 2010-06-24 13:44       ` Diego Elio “Flameeyes” Pettenò
  2010-06-24 13:58         ` Vlad Yasevich
  0 siblings, 1 reply; 6+ messages in thread
From: Diego Elio “Flameeyes” Pettenò @ 2010-06-24 13:44 UTC (permalink / raw)
  To: Vlad Yasevich; +Cc: linux-kernel, linux-sctp

Il giorno gio, 24/06/2010 alle 09.40 -0400, Vlad Yasevich ha scritto:
> You don't call accept() on an SCTP SEQPACKET socket.  You can just
> read from it.

Okay I guess I'll send a patch to the man page to fix that then.

> This way, you'll ignore listening SOCK_STREAM sockets which will not
> have any
> data anyway, but you'll check out listening SOCK_SEQPACKET sockets
> that may have
> data waiting on them. 

Ah I think I see what you mean here: SIOCINQ would work for TCP-style
ESTABLISHED sockets _and_ SEQPACKET LISTENING sockets, right?

Will send the updated patch in a moment.

-- 
Diego Elio Pettenò — “Flameeyes”
http://blog.flameeyes.eu/

If you found a .asc file in this mail and know not what it is,
it's a GnuPG digital signature: http://www.gnupg.org/



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

* Re: [PATCH] sctp: implement SIOCINQ ioctl()
  2010-06-24 13:44       ` Diego Elio “Flameeyes” Pettenò
@ 2010-06-24 13:58         ` Vlad Yasevich
  0 siblings, 0 replies; 6+ messages in thread
From: Vlad Yasevich @ 2010-06-24 13:58 UTC (permalink / raw)
  To: Diego Elio “Flameeyes” Pettenò; +Cc: linux-kernel, linux-sctp



Diego Elio “Flameeyes” Pettenò wrote:
> Il giorno gio, 24/06/2010 alle 09.40 -0400, Vlad Yasevich ha scritto:
>> You don't call accept() on an SCTP SEQPACKET socket.  You can just
>> read from it.
> 
> Okay I guess I'll send a patch to the man page to fix that then.

I don't think the man page needs an update.  This is just an SCTP-ism.
There are other protocols using SOCK_SEQPACKET that implement and support
accept() call.

The SCTP api spec decided that it wouldn't support accept() and we have to
follow it.


> 
>> This way, you'll ignore listening SOCK_STREAM sockets which will not
>> have any
>> data anyway, but you'll check out listening SOCK_SEQPACKET sockets
>> that may have
>> data waiting on them. 
> 
> Ah I think I see what you mean here: SIOCINQ would work for TCP-style
> ESTABLISHED sockets _and_ SEQPACKET LISTENING sockets, right?

Right.

-vlad

> 
> Will send the updated patch in a moment.
> 

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

end of thread, other threads:[~2010-06-24 13:58 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-06-23 21:37 [PATCH] sctp: implement SIOCINQ ioctl() Diego Elio 'Flameeyes' Pettenò
2010-06-24 13:19 ` Vlad Yasevich
2010-06-24 13:20   ` Diego Elio “Flameeyes” Pettenò
2010-06-24 13:40     ` Vlad Yasevich
2010-06-24 13:44       ` Diego Elio “Flameeyes” Pettenò
2010-06-24 13:58         ` Vlad Yasevich

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox