From: Marcel Holtmann Date: Thu, 19 Apr 2012 12:37:58 +0000 (+0200) Subject: Bluetooth: Restrict to one SCO listening socket X-Git-Tag: v3.5-rc1~101^2~6^2^2^2~49 X-Git-Url: https://openfabrics.org/gitweb/?a=commitdiff_plain;h=fb3340594bd6630c27e31ddeff25b7002fb4558e;p=~emulex%2Finfiniband.git Bluetooth: Restrict to one SCO listening socket The SCO sockets are only identified by its address. So only allow one SCO socket in listening state per address or BDADDR_ANY. Signed-off-by: Marcel Holtmann Signed-off-by: Gustavo Padovan --- diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c index c75cd7b07d1..bf1af0b1497 100644 --- a/net/bluetooth/sco.c +++ b/net/bluetooth/sco.c @@ -273,17 +273,20 @@ drop: } /* -------- Socket interface ---------- */ -static struct sock *__sco_get_sock_by_addr(bdaddr_t *ba) +static struct sock *__sco_get_sock_listen_by_addr(bdaddr_t *ba) { - struct sock *sk; struct hlist_node *node; + struct sock *sk; + + sk_for_each(sk, node, &sco_sk_list.head) { + if (sk->sk_state != BT_LISTEN) + continue; - sk_for_each(sk, node, &sco_sk_list.head) if (!bacmp(&bt_sk(sk)->src, ba)) - goto found; - sk = NULL; -found: - return sk; + return sk; + } + + return NULL; } /* Find socket listening on source bdaddr. @@ -529,6 +532,7 @@ done: static int sco_sock_listen(struct socket *sock, int backlog) { struct sock *sk = sock->sk; + bdaddr_t *src = &bt_sk(sk)->src; int err = 0; BT_DBG("sk %p backlog %d", sk, backlog); @@ -545,10 +549,21 @@ static int sco_sock_listen(struct socket *sock, int backlog) goto done; } + write_lock(&sco_sk_list.lock); + + if (__sco_get_sock_listen_by_addr(src)) { + err = -EADDRINUSE; + goto unlock; + } + sk->sk_max_ack_backlog = backlog; sk->sk_ack_backlog = 0; + sk->sk_state = BT_LISTEN; +unlock: + write_unlock(&sco_sk_list.lock); + done: release_sock(sk); return err;