Bluetooth: ISO: Allow binding a PA sync socket
authorIulia Tanasescu <iulia.tanasescu@nxp.com>
Tue, 24 Oct 2023 10:57:35 +0000 (13:57 +0300)
committerLuiz Augusto von Dentz <luiz.von.dentz@intel.com>
Fri, 22 Dec 2023 17:47:15 +0000 (12:47 -0500)
This makes it possible to bind a PA sync socket to a number of BISes
before issuing the BIG Create Sync command.

Signed-off-by: Iulia Tanasescu <iulia.tanasescu@nxp.com>
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
net/bluetooth/iso.c

index 07b80e97aead5d8ac5497676768a0f7a3142a591..e01b6abe36fbc7cd82a4f24e73b352c6242d05a9 100644 (file)
@@ -792,27 +792,75 @@ static int iso_sock_bind_bc(struct socket *sock, struct sockaddr *addr,
        BT_DBG("sk %p bc_sid %u bc_num_bis %u", sk, sa->iso_bc->bc_sid,
               sa->iso_bc->bc_num_bis);
 
-       if (addr_len > sizeof(*sa) + sizeof(*sa->iso_bc))
+       if (addr_len != sizeof(*sa) + sizeof(*sa->iso_bc))
                return -EINVAL;
 
        bacpy(&iso_pi(sk)->dst, &sa->iso_bc->bc_bdaddr);
+
+       /* Check if the address type is of LE type */
+       if (!bdaddr_type_is_le(sa->iso_bc->bc_bdaddr_type))
+               return -EINVAL;
+
        iso_pi(sk)->dst_type = sa->iso_bc->bc_bdaddr_type;
        iso_pi(sk)->sync_handle = -1;
+
+       if (sa->iso_bc->bc_sid > 0x0f)
+               return -EINVAL;
+
        iso_pi(sk)->bc_sid = sa->iso_bc->bc_sid;
+
+       if (sa->iso_bc->bc_num_bis > ISO_MAX_NUM_BIS)
+               return -EINVAL;
+
        iso_pi(sk)->bc_num_bis = sa->iso_bc->bc_num_bis;
 
-       for (i = 0; i < iso_pi(sk)->bc_num_bis; i++) {
+       for (i = 0; i < iso_pi(sk)->bc_num_bis; i++)
                if (sa->iso_bc->bc_bis[i] < 0x01 ||
                    sa->iso_bc->bc_bis[i] > 0x1f)
                        return -EINVAL;
 
-               memcpy(iso_pi(sk)->bc_bis, sa->iso_bc->bc_bis,
-                      iso_pi(sk)->bc_num_bis);
-       }
+       memcpy(iso_pi(sk)->bc_bis, sa->iso_bc->bc_bis,
+              iso_pi(sk)->bc_num_bis);
 
        return 0;
 }
 
+static int iso_sock_bind_pa_sk(struct sock *sk, struct sockaddr_iso *sa,
+                              int addr_len)
+{
+       int err = 0;
+
+       if (sk->sk_type != SOCK_SEQPACKET) {
+               err = -EINVAL;
+               goto done;
+       }
+
+       if (addr_len != sizeof(*sa) + sizeof(*sa->iso_bc)) {
+               err = -EINVAL;
+               goto done;
+       }
+
+       if (sa->iso_bc->bc_num_bis > ISO_MAX_NUM_BIS) {
+               err = -EINVAL;
+               goto done;
+       }
+
+       iso_pi(sk)->bc_num_bis = sa->iso_bc->bc_num_bis;
+
+       for (int i = 0; i < iso_pi(sk)->bc_num_bis; i++)
+               if (sa->iso_bc->bc_bis[i] < 0x01 ||
+                   sa->iso_bc->bc_bis[i] > 0x1f) {
+                       err = -EINVAL;
+                       goto done;
+               }
+
+       memcpy(iso_pi(sk)->bc_bis, sa->iso_bc->bc_bis,
+              iso_pi(sk)->bc_num_bis);
+
+done:
+       return err;
+}
+
 static int iso_sock_bind(struct socket *sock, struct sockaddr *addr,
                         int addr_len)
 {
@@ -828,6 +876,15 @@ static int iso_sock_bind(struct socket *sock, struct sockaddr *addr,
 
        lock_sock(sk);
 
+       /* Allow the user to bind a PA sync socket to a number
+        * of BISes to sync to.
+        */
+       if (sk->sk_state == BT_CONNECT2 &&
+           test_bit(BT_SK_PA_SYNC, &iso_pi(sk)->flags)) {
+               err = iso_sock_bind_pa_sk(sk, sa, addr_len);
+               goto done;
+       }
+
        if (sk->sk_state != BT_OPEN) {
                err = -EBADFD;
                goto done;