Skip to content

Commit d2ab0ac

Browse files
holtmannJohan Hedberg
authored andcommitted
Bluetooth: Add support for storing LE white list entries
The current LE white list entries require storing in the HCI controller structure. So provide a storage and access functions for it. In addition export the current list via debugfs. Signed-off-by: Marcel Holtmann <[email protected]> Signed-off-by: Johan Hedberg <[email protected]>
1 parent 747d3f0 commit d2ab0ac

File tree

2 files changed

+97
-0
lines changed

2 files changed

+97
-0
lines changed

include/net/bluetooth/hci_core.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -284,6 +284,7 @@ struct hci_dev {
284284
struct list_head long_term_keys;
285285
struct list_head identity_resolving_keys;
286286
struct list_head remote_oob_data;
287+
struct list_head le_white_list;
287288
struct list_head le_conn_params;
288289
struct list_head pend_le_conns;
289290

@@ -799,6 +800,12 @@ struct bdaddr_list *hci_blacklist_lookup(struct hci_dev *hdev,
799800
int hci_blacklist_add(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type);
800801
int hci_blacklist_del(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type);
801802

803+
struct bdaddr_list *hci_white_list_lookup(struct hci_dev *hdev,
804+
bdaddr_t *bdaddr, u8 type);
805+
void hci_white_list_clear(struct hci_dev *hdev);
806+
int hci_white_list_add(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type);
807+
int hci_white_list_del(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type);
808+
802809
struct hci_conn_params *hci_conn_params_lookup(struct hci_dev *hdev,
803810
bdaddr_t *addr, u8 addr_type);
804811
int hci_conn_params_add(struct hci_dev *hdev, bdaddr_t *addr, u8 addr_type,

net/bluetooth/hci_core.c

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -702,6 +702,31 @@ static const struct file_operations force_static_address_fops = {
702702
.llseek = default_llseek,
703703
};
704704

705+
static int white_list_show(struct seq_file *f, void *ptr)
706+
{
707+
struct hci_dev *hdev = f->private;
708+
struct bdaddr_list *b;
709+
710+
hci_dev_lock(hdev);
711+
list_for_each_entry(b, &hdev->le_white_list, list)
712+
seq_printf(f, "%pMR (type %u)\n", &b->bdaddr, b->bdaddr_type);
713+
hci_dev_unlock(hdev);
714+
715+
return 0;
716+
}
717+
718+
static int white_list_open(struct inode *inode, struct file *file)
719+
{
720+
return single_open(file, white_list_show, inode->i_private);
721+
}
722+
723+
static const struct file_operations white_list_fops = {
724+
.open = white_list_open,
725+
.read = seq_read,
726+
.llseek = seq_lseek,
727+
.release = single_release,
728+
};
729+
705730
static int identity_resolving_keys_show(struct seq_file *f, void *ptr)
706731
{
707732
struct hci_dev *hdev = f->private;
@@ -1786,6 +1811,8 @@ static int __hci_init(struct hci_dev *hdev)
17861811

17871812
debugfs_create_u8("white_list_size", 0444, hdev->debugfs,
17881813
&hdev->le_white_list_size);
1814+
debugfs_create_file("white_list", 0444, hdev->debugfs, hdev,
1815+
&white_list_fops);
17891816
debugfs_create_file("identity_resolving_keys", 0400,
17901817
hdev->debugfs, hdev,
17911818
&identity_resolving_keys_fops);
@@ -3294,6 +3321,67 @@ int hci_blacklist_del(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type)
32943321
return mgmt_device_unblocked(hdev, bdaddr, type);
32953322
}
32963323

3324+
struct bdaddr_list *hci_white_list_lookup(struct hci_dev *hdev,
3325+
bdaddr_t *bdaddr, u8 type)
3326+
{
3327+
struct bdaddr_list *b;
3328+
3329+
list_for_each_entry(b, &hdev->le_white_list, list) {
3330+
if (!bacmp(&b->bdaddr, bdaddr) && b->bdaddr_type == type)
3331+
return b;
3332+
}
3333+
3334+
return NULL;
3335+
}
3336+
3337+
void hci_white_list_clear(struct hci_dev *hdev)
3338+
{
3339+
struct list_head *p, *n;
3340+
3341+
list_for_each_safe(p, n, &hdev->le_white_list) {
3342+
struct bdaddr_list *b = list_entry(p, struct bdaddr_list, list);
3343+
3344+
list_del(p);
3345+
kfree(b);
3346+
}
3347+
}
3348+
3349+
int hci_white_list_add(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type)
3350+
{
3351+
struct bdaddr_list *entry;
3352+
3353+
if (!bacmp(bdaddr, BDADDR_ANY))
3354+
return -EBADF;
3355+
3356+
entry = kzalloc(sizeof(struct bdaddr_list), GFP_KERNEL);
3357+
if (!entry)
3358+
return -ENOMEM;
3359+
3360+
bacpy(&entry->bdaddr, bdaddr);
3361+
entry->bdaddr_type = type;
3362+
3363+
list_add(&entry->list, &hdev->le_white_list);
3364+
3365+
return 0;
3366+
}
3367+
3368+
int hci_white_list_del(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type)
3369+
{
3370+
struct bdaddr_list *entry;
3371+
3372+
if (!bacmp(bdaddr, BDADDR_ANY))
3373+
return -EBADF;
3374+
3375+
entry = hci_white_list_lookup(hdev, bdaddr, type);
3376+
if (!entry)
3377+
return -ENOENT;
3378+
3379+
list_del(&entry->list);
3380+
kfree(entry);
3381+
3382+
return 0;
3383+
}
3384+
32973385
/* This function requires the caller holds hdev->lock */
32983386
struct hci_conn_params *hci_conn_params_lookup(struct hci_dev *hdev,
32993387
bdaddr_t *addr, u8 addr_type)
@@ -3692,6 +3780,7 @@ struct hci_dev *hci_alloc_dev(void)
36923780
INIT_LIST_HEAD(&hdev->long_term_keys);
36933781
INIT_LIST_HEAD(&hdev->identity_resolving_keys);
36943782
INIT_LIST_HEAD(&hdev->remote_oob_data);
3783+
INIT_LIST_HEAD(&hdev->le_white_list);
36953784
INIT_LIST_HEAD(&hdev->le_conn_params);
36963785
INIT_LIST_HEAD(&hdev->pend_le_conns);
36973786
INIT_LIST_HEAD(&hdev->conn_hash.list);
@@ -3894,6 +3983,7 @@ void hci_unregister_dev(struct hci_dev *hdev)
38943983
hci_smp_ltks_clear(hdev);
38953984
hci_smp_irks_clear(hdev);
38963985
hci_remote_oob_data_clear(hdev);
3986+
hci_white_list_clear(hdev);
38973987
hci_conn_params_clear(hdev);
38983988
hci_pend_le_conns_clear(hdev);
38993989
hci_dev_unlock(hdev);

0 commit comments

Comments
 (0)