From f214b6e6568bc7c78d5101434f7b279a88a6bc92 Mon Sep 17 00:00:00 2001 From: Inga Stotland Date: Tue, 11 Oct 2011 08:56:15 -0700 Subject: [PATCH] Bluetooth: Socket lookup for a fixed L2CAP channel Socket lookup for a fixed channel should be done based on both remote and local device addresses. Change-Id: I35f39bea8ade6fd5d8695640251efc54bf21beae Signed-off-by: Inga Stotland --- net/bluetooth/l2cap_core.c | 33 ++++++++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index d103bef6b3a..dea21c1427e 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -909,6 +909,37 @@ static void l2cap_conn_start(struct l2cap_conn *conn) } } +/* Find socket with fixed cid with given source and destination bdaddrs. + * Returns closest match, locked. + */ +static struct sock *l2cap_get_sock_by_fixed_scid(int state, + __le16 cid, bdaddr_t *src, bdaddr_t *dst) +{ + struct sock *sk = NULL, *sk1 = NULL; + struct hlist_node *node; + + read_lock(&l2cap_sk_list.lock); + + sk_for_each(sk, node, &l2cap_sk_list.head) { + if (state && sk->sk_state != state) + continue; + + if (l2cap_pi(sk)->scid == cid && !bacmp(&bt_sk(sk)->dst, dst)) { + /* Exact match. */ + if (!bacmp(&bt_sk(sk)->src, src)) + break; + + /* Closest match */ + if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY)) + sk1 = sk; + } + } + + read_unlock(&l2cap_sk_list.lock); + + return node ? sk : sk1; +} + /* Find socket with cid and source bdaddr. * Returns closest match, locked. */ @@ -7051,7 +7082,7 @@ static inline int l2cap_att_channel(struct l2cap_conn *conn, __le16 cid, struct { struct sock *sk; - sk = l2cap_get_sock_by_scid(0, cid, conn->src); + sk = l2cap_get_sock_by_fixed_scid(0, cid, conn->src, conn->dst); if (!sk) goto drop;