Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ff353d86 authored by Samuel Ortiz's avatar Samuel Ortiz Committed by John W. Linville
Browse files

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: default avatarSamuel Ortiz <sameo@linux.intel.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 0f909361
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -448,6 +448,8 @@ static struct nfc_llcp_sock *nfc_llcp_sock_get(struct nfc_llcp_local *local,
{
	struct nfc_llcp_sock *sock, *llcp_sock, *n;

	pr_debug("ssap dsap %d %d\n", ssap, dsap);

	if (ssap == 0 && dsap == 0)
		return NULL;

@@ -783,6 +785,7 @@ static void nfc_llcp_recv_disc(struct nfc_llcp_local *local,
static void nfc_llcp_recv_cc(struct nfc_llcp_local *local, struct sk_buff *skb)
{
	struct nfc_llcp_sock *llcp_sock;
	struct sock *sk;
	u8 dsap, ssap;

	dsap = nfc_llcp_dsap(skb);
@@ -801,10 +804,14 @@ static void nfc_llcp_recv_cc(struct nfc_llcp_local *local, struct sk_buff *skb)
	}

	llcp_sock->dsap = ssap;
	sk = &llcp_sock->sk;

	nfc_llcp_parse_tlv(local, &skb->data[LLCP_HEADER_SIZE],
			   skb->len - LLCP_HEADER_SIZE);

	sk->sk_state = LLCP_CONNECTED;
	sk->sk_state_change(sk);

	nfc_llcp_sock_put(llcp_sock);
}

+41 −1
Original line number Diff line number Diff line
@@ -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: