diff options
author | Gustavo F. Padovan <padovan@profusion.mobi> | 2011-04-07 15:40:25 -0400 |
---|---|---|
committer | Gustavo F. Padovan <padovan@profusion.mobi> | 2011-04-13 11:20:02 -0400 |
commit | 9f69bda6aa8b365169b4a6fd35432ee40574d661 (patch) | |
tree | 5bd48c861e6e17a339367f0ad4dd7f81093d6663 /net/bluetooth/l2cap_core.c | |
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/bluetooth/l2cap_core.c')
-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 97827506dc94..c9c1f9257a91 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c | |||
@@ -3728,6 +3728,36 @@ done: | |||
3728 | return 0; | 3728 | return 0; |
3729 | } | 3729 | } |
3730 | 3730 | ||
3731 | static inline int l2cap_att_channel(struct l2cap_conn *conn, __le16 cid, struct sk_buff *skb) | ||
3732 | { | ||
3733 | struct sock *sk; | ||
3734 | |||
3735 | sk = l2cap_get_sock_by_scid(0, cid, conn->src); | ||
3736 | if (!sk) | ||
3737 | goto drop; | ||
3738 | |||
3739 | bh_lock_sock(sk); | ||
3740 | |||
3741 | BT_DBG("sk %p, len %d", sk, skb->len); | ||
3742 | |||
3743 | if (sk->sk_state != BT_BOUND && sk->sk_state != BT_CONNECTED) | ||
3744 | goto drop; | ||
3745 | |||
3746 | if (l2cap_pi(sk)->imtu < skb->len) | ||
3747 | goto drop; | ||
3748 | |||
3749 | if (!sock_queue_rcv_skb(sk, skb)) | ||
3750 | goto done; | ||
3751 | |||
3752 | drop: | ||
3753 | kfree_skb(skb); | ||
3754 | |||
3755 | done: | ||
3756 | if (sk) | ||
3757 | bh_unlock_sock(sk); | ||
3758 | return 0; | ||
3759 | } | ||
3760 | |||
3731 | static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb) | 3761 | static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb) |
3732 | { | 3762 | { |
3733 | struct l2cap_hdr *lh = (void *) skb->data; | 3763 | struct l2cap_hdr *lh = (void *) skb->data; |
@@ -3757,6 +3787,10 @@ static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb) | |||
3757 | l2cap_conless_channel(conn, psm, skb); | 3787 | l2cap_conless_channel(conn, psm, skb); |
3758 | break; | 3788 | break; |
3759 | 3789 | ||
3790 | case L2CAP_CID_LE_DATA: | ||
3791 | l2cap_att_channel(conn, cid, skb); | ||
3792 | break; | ||
3793 | |||
3760 | default: | 3794 | default: |
3761 | l2cap_data_channel(conn, cid, skb); | 3795 | l2cap_data_channel(conn, cid, skb); |
3762 | break; | 3796 | break; |