diff options
author | Gustavo F. Padovan <padovan@profusion.mobi> | 2011-04-07 16:40:25 -0300 |
---|---|---|
committer | Gustavo F. Padovan <padovan@profusion.mobi> | 2011-04-13 12:20:02 -0300 |
commit | 9f69bda6aa8b365169b4a6fd35432ee40574d661 (patch) | |
tree | 5bd48c861e6e17a339367f0ad4dd7f81093d6663 /net | |
parent | 0733119c0bed37eda4bb832d049939a0dc53a233 (diff) |
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')
-rw-r--r-- | net/bluetooth/l2cap_core.c | 34 |
1 files changed, 34 insertions, 0 deletions
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index 97827506dc9..c9c1f9257a9 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; |