mirror of https://gitee.com/openkylin/linux.git
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>
This commit is contained in:
parent
0f90936106
commit
ff353d86a9
|
@ -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;
|
struct nfc_llcp_sock *sock, *llcp_sock, *n;
|
||||||
|
|
||||||
|
pr_debug("ssap dsap %d %d\n", ssap, dsap);
|
||||||
|
|
||||||
if (ssap == 0 && dsap == 0)
|
if (ssap == 0 && dsap == 0)
|
||||||
return NULL;
|
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)
|
static void nfc_llcp_recv_cc(struct nfc_llcp_local *local, struct sk_buff *skb)
|
||||||
{
|
{
|
||||||
struct nfc_llcp_sock *llcp_sock;
|
struct nfc_llcp_sock *llcp_sock;
|
||||||
|
struct sock *sk;
|
||||||
u8 dsap, ssap;
|
u8 dsap, ssap;
|
||||||
|
|
||||||
dsap = nfc_llcp_dsap(skb);
|
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;
|
llcp_sock->dsap = ssap;
|
||||||
|
sk = &llcp_sock->sk;
|
||||||
|
|
||||||
nfc_llcp_parse_tlv(local, &skb->data[LLCP_HEADER_SIZE],
|
nfc_llcp_parse_tlv(local, &skb->data[LLCP_HEADER_SIZE],
|
||||||
skb->len - LLCP_HEADER_SIZE);
|
skb->len - LLCP_HEADER_SIZE);
|
||||||
|
|
||||||
|
sk->sk_state = LLCP_CONNECTED;
|
||||||
|
sk->sk_state_change(sk);
|
||||||
|
|
||||||
nfc_llcp_sock_put(llcp_sock);
|
nfc_llcp_sock_put(llcp_sock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -27,6 +27,42 @@
|
||||||
#include "../nfc.h"
|
#include "../nfc.h"
|
||||||
#include "llcp.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 = {
|
static struct proto llcp_sock_proto = {
|
||||||
.name = "NFC_LLCP",
|
.name = "NFC_LLCP",
|
||||||
.owner = THIS_MODULE,
|
.owner = THIS_MODULE,
|
||||||
|
@ -462,9 +498,13 @@ static int llcp_sock_connect(struct socket *sock, struct sockaddr *_addr,
|
||||||
if (ret)
|
if (ret)
|
||||||
goto put_dev;
|
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);
|
release_sock(sk);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
put_dev:
|
put_dev:
|
||||||
|
|
Loading…
Reference in New Issue