Commit fb334059 authored by Marcel Holtmann's avatar Marcel Holtmann Committed by Gustavo Padovan

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: default avatarMarcel Holtmann <marcel@holtmann.org>
Signed-off-by: default avatarGustavo Padovan <gustavo@padovan.org>
parent 8ed21f7e
...@@ -273,17 +273,20 @@ static inline void sco_recv_frame(struct sco_conn *conn, struct sk_buff *skb) ...@@ -273,17 +273,20 @@ static inline void sco_recv_frame(struct sco_conn *conn, struct sk_buff *skb)
} }
/* -------- Socket interface ---------- */ /* -------- 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 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)) if (!bacmp(&bt_sk(sk)->src, ba))
goto found; return sk;
sk = NULL; }
found:
return sk; return NULL;
} }
/* Find socket listening on source bdaddr. /* Find socket listening on source bdaddr.
...@@ -529,6 +532,7 @@ static int sco_sock_connect(struct socket *sock, struct sockaddr *addr, int alen ...@@ -529,6 +532,7 @@ static int sco_sock_connect(struct socket *sock, struct sockaddr *addr, int alen
static int sco_sock_listen(struct socket *sock, int backlog) static int sco_sock_listen(struct socket *sock, int backlog)
{ {
struct sock *sk = sock->sk; struct sock *sk = sock->sk;
bdaddr_t *src = &bt_sk(sk)->src;
int err = 0; int err = 0;
BT_DBG("sk %p backlog %d", sk, backlog); BT_DBG("sk %p backlog %d", sk, backlog);
...@@ -545,10 +549,21 @@ static int sco_sock_listen(struct socket *sock, int backlog) ...@@ -545,10 +549,21 @@ static int sco_sock_listen(struct socket *sock, int backlog)
goto done; 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_max_ack_backlog = backlog;
sk->sk_ack_backlog = 0; sk->sk_ack_backlog = 0;
sk->sk_state = BT_LISTEN; sk->sk_state = BT_LISTEN;
unlock:
write_unlock(&sco_sk_list.lock);
done: done:
release_sock(sk); release_sock(sk);
return err; return err;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment