typedef bool (*iso_sock_match_t)(struct sock *sk, void *data);
-static struct sock *iso_get_sock(bdaddr_t *src, bdaddr_t *dst,
- enum bt_sock_state state,
+static struct sock *iso_get_sock(struct hci_dev *hdev, bdaddr_t *src,
+ bdaddr_t *dst, enum bt_sock_state state,
iso_sock_match_t match, void *data);
/* ---- ISO timers ---- */
* match func data - pass -1 to ignore
* Returns closest match.
*/
-static struct sock *iso_get_sock(bdaddr_t *src, bdaddr_t *dst,
- enum bt_sock_state state,
+static struct sock *iso_get_sock(struct hci_dev *hdev, bdaddr_t *src,
+ bdaddr_t *dst, enum bt_sock_state state,
iso_sock_match_t match, void *data)
{
struct sock *sk = NULL, *sk1 = NULL;
continue;
/* Match Broadcast destination */
- if (bacmp(dst, BDADDR_ANY) && bacmp(&iso_pi(sk)->dst, dst))
- continue;
+ if (bacmp(dst, BDADDR_ANY) && bacmp(&iso_pi(sk)->dst, dst)) {
+ struct smp_irk *irk1, *irk2;
+
+ /* Check if destination is an RPA that we can resolve */
+ irk1 = hci_find_irk_by_rpa(hdev, dst);
+ if (!irk1)
+ continue;
+
+ /* Match with identity address */
+ if (bacmp(&iso_pi(sk)->dst, &irk1->bdaddr)) {
+ /* Check if socket destination address is also
+ * an RPA and if the IRK matches.
+ */
+ irk2 = hci_find_irk_by_rpa(hdev,
+ &iso_pi(sk)->dst);
+ if (!irk2 || irk1 != irk2)
+ continue;
+ }
+ }
/* Use Match function if provided */
if (match && !match(sk, data))
struct hci_ev_le_pa_sync_established *ev2 = NULL;
struct hci_ev_le_per_adv_report *ev3 = NULL;
struct hci_conn *hcon;
+ struct hci_dev *hdev;
BT_DBG("conn %p", conn);
if (!hcon)
return;
+ hdev = hcon->hdev;
+
if (test_bit(HCI_CONN_BIG_SYNC, &hcon->flags)) {
/* A BIS slave hcon is notified to the ISO layer
* after the Command Complete for the LE Setup
* ISO Data Path command is received. Get the
* parent socket that matches the hcon BIG handle.
*/
- parent = iso_get_sock(&hcon->src, &hcon->dst,
+ parent = iso_get_sock(hdev, &hcon->src, &hcon->dst,
BT_LISTEN, iso_match_big_hcon,
hcon);
} else if (test_bit(HCI_CONN_BIG_SYNC_FAILED, &hcon->flags)) {
HCI_EVT_LE_BIG_SYNC_ESTABLISHED);
/* Get reference to PA sync parent socket, if it exists */
- parent = iso_get_sock(&hcon->src, &hcon->dst,
+ parent = iso_get_sock(hdev, &hcon->src, &hcon->dst,
BT_LISTEN,
iso_match_pa_sync_flag,
NULL);
if (!parent && ev)
- parent = iso_get_sock(&hcon->src,
+ parent = iso_get_sock(hdev, &hcon->src,
&hcon->dst,
BT_LISTEN,
iso_match_big, ev);
ev2 = hci_recv_event_data(hcon->hdev,
HCI_EV_LE_PA_SYNC_ESTABLISHED);
if (ev2)
- parent = iso_get_sock(&hcon->src,
+ parent = iso_get_sock(hdev, &hcon->src,
&hcon->dst,
BT_LISTEN,
iso_match_sid, ev2);
ev3 = hci_recv_event_data(hcon->hdev,
HCI_EV_LE_PER_ADV_REPORT);
if (ev3)
- parent = iso_get_sock(&hcon->src,
+ parent = iso_get_sock(hdev, &hcon->src,
&hcon->dst,
BT_LISTEN,
iso_match_sync_handle_pa_report,
}
if (!parent)
- parent = iso_get_sock(&hcon->src, BDADDR_ANY,
+ parent = iso_get_sock(hdev, &hcon->src, BDADDR_ANY,
BT_LISTEN, NULL, NULL);
if (!parent)
*/
ev1 = hci_recv_event_data(hdev, HCI_EV_LE_PA_SYNC_ESTABLISHED);
if (ev1) {
- sk = iso_get_sock(&hdev->bdaddr, bdaddr, BT_LISTEN,
+ sk = iso_get_sock(hdev, &hdev->bdaddr, bdaddr, BT_LISTEN,
iso_match_sid, ev1);
if (sk && !ev1->status) {
iso_pi(sk)->sync_handle = le16_to_cpu(ev1->handle);
ev1a = hci_recv_event_data(hdev, HCI_EV_LE_PAST_RECEIVED);
if (ev1a) {
- sk = iso_get_sock(&hdev->bdaddr, bdaddr, BT_LISTEN,
+ sk = iso_get_sock(hdev, &hdev->bdaddr, bdaddr, BT_LISTEN,
iso_match_sid_past, ev1a);
if (sk && !ev1a->status) {
iso_pi(sk)->sync_handle = le16_to_cpu(ev1a->sync_handle);
ev2 = hci_recv_event_data(hdev, HCI_EVT_LE_BIG_INFO_ADV_REPORT);
if (ev2) {
/* Check if BIGInfo report has already been handled */
- sk = iso_get_sock(&hdev->bdaddr, bdaddr, BT_CONNECTED,
+ sk = iso_get_sock(hdev, &hdev->bdaddr, bdaddr, BT_CONNECTED,
iso_match_sync_handle, ev2);
if (sk) {
sock_put(sk);
}
/* Try to get PA sync socket, if it exists */
- sk = iso_get_sock(&hdev->bdaddr, bdaddr, BT_CONNECT2,
+ sk = iso_get_sock(hdev, &hdev->bdaddr, bdaddr, BT_CONNECT2,
iso_match_sync_handle, ev2);
if (!sk)
- sk = iso_get_sock(&hdev->bdaddr, bdaddr,
+ sk = iso_get_sock(hdev, &hdev->bdaddr, bdaddr,
BT_LISTEN,
iso_match_sync_handle,
ev2);
u8 *base;
struct hci_conn *hcon;
- sk = iso_get_sock(&hdev->bdaddr, bdaddr, BT_LISTEN,
+ sk = iso_get_sock(hdev, &hdev->bdaddr, bdaddr, BT_LISTEN,
iso_match_sync_handle_pa_report, ev3);
if (!sk)
goto done;
hcon->le_per_adv_data_len = 0;
}
} else {
- sk = iso_get_sock(&hdev->bdaddr, BDADDR_ANY,
+ sk = iso_get_sock(hdev, &hdev->bdaddr, BDADDR_ANY,
BT_LISTEN, NULL, NULL);
}