summaryrefslogtreecommitdiff
path: root/net/bluetooth/l2cap_core.c
diff options
context:
space:
mode:
authorGustavo F. Padovan <padovan@profusion.mobi>2011-04-07 16:40:25 -0300
committerGustavo F. Padovan <padovan@profusion.mobi>2011-04-13 12:20:02 -0300
commit9f69bda6aa8b365169b4a6fd35432ee40574d661 (patch)
tree5bd48c861e6e17a339367f0ad4dd7f81093d6663 /net/bluetooth/l2cap_core.c
parent0733119c0bed37eda4bb832d049939a0dc53a233 (diff)
downloadlwn-9f69bda6aa8b365169b4a6fd35432ee40574d661.tar.gz
lwn-9f69bda6aa8b365169b4a6fd35432ee40574d661.zip
Bluetooth: Add proper handling of received LE data
Despite it works, handling through l2cap_data_channel() is wrongs. That function should handle only connection oriented data. Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi>
Diffstat (limited to 'net/bluetooth/l2cap_core.c')
-rw-r--r--net/bluetooth/l2cap_core.c34
1 files changed, 34 insertions, 0 deletions
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index 97827506dc94..c9c1f9257a91 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -3728,6 +3728,36 @@ done:
return 0;
}
+static inline int l2cap_att_channel(struct l2cap_conn *conn, __le16 cid, struct sk_buff *skb)
+{
+ struct sock *sk;
+
+ sk = l2cap_get_sock_by_scid(0, cid, conn->src);
+ if (!sk)
+ goto drop;
+
+ bh_lock_sock(sk);
+
+ BT_DBG("sk %p, len %d", sk, skb->len);
+
+ if (sk->sk_state != BT_BOUND && sk->sk_state != BT_CONNECTED)
+ goto drop;
+
+ if (l2cap_pi(sk)->imtu < skb->len)
+ goto drop;
+
+ if (!sock_queue_rcv_skb(sk, skb))
+ goto done;
+
+drop:
+ kfree_skb(skb);
+
+done:
+ if (sk)
+ bh_unlock_sock(sk);
+ return 0;
+}
+
static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb)
{
struct l2cap_hdr *lh = (void *) skb->data;
@@ -3757,6 +3787,10 @@ static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb)
l2cap_conless_channel(conn, psm, skb);
break;
+ case L2CAP_CID_LE_DATA:
+ l2cap_att_channel(conn, cid, skb);
+ break;
+
default:
l2cap_data_channel(conn, cid, skb);
break;