summaryrefslogtreecommitdiffstats
path: root/net/nfc/llcp/sock.c
diff options
context:
space:
mode:
authorSamuel Ortiz <sameo@linux.intel.com>2012-05-07 12:31:19 +0200
committerJohn W. Linville <linville@tuxdriver.com>2012-05-15 17:28:01 -0400
commitff353d86a92ee709e18fa485423dbaa7a52af8f3 (patch)
tree15e7400909f0d314b622135c4e447d0e687950a0 /net/nfc/llcp/sock.c
parent0f909361062d42b0ff7c6522e2347b56a0bf43cc (diff)
downloadlinux-ff353d86a92ee709e18fa485423dbaa7a52af8f3.tar.gz
linux-ff353d86a92ee709e18fa485423dbaa7a52af8f3.tar.xz
linux-ff353d86a92ee709e18fa485423dbaa7a52af8f3.zip
NFC: LLCP connect must wait for a CC frame
Blocking sockets should sleep on a CC (Connection Complete) reception from the connect() call. Signed-off-by: Samuel Ortiz <sameo@linux.intel.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/nfc/llcp/sock.c')
-rw-r--r--net/nfc/llcp/sock.c42
1 files changed, 41 insertions, 1 deletions
diff --git a/net/nfc/llcp/sock.c b/net/nfc/llcp/sock.c
index c13e02ebdef9..99196d3b84eb 100644
--- a/net/nfc/llcp/sock.c
+++ b/net/nfc/llcp/sock.c
@@ -27,6 +27,42 @@
#include "../nfc.h"
#include "llcp.h"
+static int sock_wait_state(struct sock *sk, int state, unsigned long timeo)
+{
+ DECLARE_WAITQUEUE(wait, current);
+ int err = 0;
+
+ pr_debug("sk %p", sk);
+
+ add_wait_queue(sk_sleep(sk), &wait);
+ set_current_state(TASK_INTERRUPTIBLE);
+
+ while (sk->sk_state != state) {
+ if (!timeo) {
+ err = -EINPROGRESS;
+ break;
+ }
+
+ if (signal_pending(current)) {
+ err = sock_intr_errno(timeo);
+ break;
+ }
+
+ release_sock(sk);
+ timeo = schedule_timeout(timeo);
+ lock_sock(sk);
+ set_current_state(TASK_INTERRUPTIBLE);
+
+ err = sock_error(sk);
+ if (err)
+ break;
+ }
+
+ __set_current_state(TASK_RUNNING);
+ remove_wait_queue(sk_sleep(sk), &wait);
+ return err;
+}
+
static struct proto llcp_sock_proto = {
.name = "NFC_LLCP",
.owner = THIS_MODULE,
@@ -462,9 +498,13 @@ static int llcp_sock_connect(struct socket *sock, struct sockaddr *_addr,
if (ret)
goto put_dev;
- sk->sk_state = LLCP_CONNECTED;
+ ret = sock_wait_state(sk, LLCP_CONNECTED,
+ sock_sndtimeo(sk, flags & O_NONBLOCK));
+ if (ret)
+ goto put_dev;
release_sock(sk);
+
return 0;
put_dev: