* [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