aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorJohan Hedberg <johan.hedberg@intel.com>2014-07-09 05:59:14 -0400
committerMarcel Holtmann <marcel@holtmann.org>2014-07-09 06:25:27 -0400
commit6659358efe617bb46237e62f7303c76e10568d70 (patch)
treecc4f21038000dd5a617580a7adc542a91c1c592c /net
parentdcc36c16c2f1c9800146c8416ee5a4c3dc974623 (diff)
Bluetooth: Introduce a whitelist for BR/EDR devices
This patch extends the Add/Remove device commands by letting user space pass BR/EDR addresses to them. The resulting entries get stored in a new hdev->whitelist list. The idea is that we can now selectively accept connections from devices in the list even though HCI_CONNECTABLE is not set (the actual implementation of this is coming in a subsequent patch). Signed-off-by: Johan Hedberg <johan.hedberg@intel.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
Diffstat (limited to 'net')
-rw-r--r--net/bluetooth/hci_core.c29
-rw-r--r--net/bluetooth/mgmt.c46
2 files changed, 73 insertions, 2 deletions
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index 705f8df7af96..728a6ee471ea 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -191,6 +191,31 @@ static const struct file_operations blacklist_fops = {
191 .release = single_release, 191 .release = single_release,
192}; 192};
193 193
194static int whitelist_show(struct seq_file *f, void *p)
195{
196 struct hci_dev *hdev = f->private;
197 struct bdaddr_list *b;
198
199 hci_dev_lock(hdev);
200 list_for_each_entry(b, &hdev->whitelist, list)
201 seq_printf(f, "%pMR (type %u)\n", &b->bdaddr, b->bdaddr_type);
202 hci_dev_unlock(hdev);
203
204 return 0;
205}
206
207static int whitelist_open(struct inode *inode, struct file *file)
208{
209 return single_open(file, whitelist_show, inode->i_private);
210}
211
212static const struct file_operations whitelist_fops = {
213 .open = whitelist_open,
214 .read = seq_read,
215 .llseek = seq_lseek,
216 .release = single_release,
217};
218
194static int uuids_show(struct seq_file *f, void *p) 219static int uuids_show(struct seq_file *f, void *p)
195{ 220{
196 struct hci_dev *hdev = f->private; 221 struct hci_dev *hdev = f->private;
@@ -1707,6 +1732,8 @@ static int __hci_init(struct hci_dev *hdev)
1707 debugfs_create_u16("hci_revision", 0444, hdev->debugfs, &hdev->hci_rev); 1732 debugfs_create_u16("hci_revision", 0444, hdev->debugfs, &hdev->hci_rev);
1708 debugfs_create_file("blacklist", 0444, hdev->debugfs, hdev, 1733 debugfs_create_file("blacklist", 0444, hdev->debugfs, hdev,
1709 &blacklist_fops); 1734 &blacklist_fops);
1735 debugfs_create_file("whitelist", 0444, hdev->debugfs, hdev,
1736 &whitelist_fops);
1710 debugfs_create_file("uuids", 0444, hdev->debugfs, hdev, &uuids_fops); 1737 debugfs_create_file("uuids", 0444, hdev->debugfs, hdev, &uuids_fops);
1711 1738
1712 debugfs_create_file("conn_info_min_age", 0644, hdev->debugfs, hdev, 1739 debugfs_create_file("conn_info_min_age", 0644, hdev->debugfs, hdev,
@@ -3825,6 +3852,7 @@ struct hci_dev *hci_alloc_dev(void)
3825 3852
3826 INIT_LIST_HEAD(&hdev->mgmt_pending); 3853 INIT_LIST_HEAD(&hdev->mgmt_pending);
3827 INIT_LIST_HEAD(&hdev->blacklist); 3854 INIT_LIST_HEAD(&hdev->blacklist);
3855 INIT_LIST_HEAD(&hdev->whitelist);
3828 INIT_LIST_HEAD(&hdev->uuids); 3856 INIT_LIST_HEAD(&hdev->uuids);
3829 INIT_LIST_HEAD(&hdev->link_keys); 3857 INIT_LIST_HEAD(&hdev->link_keys);
3830 INIT_LIST_HEAD(&hdev->long_term_keys); 3858 INIT_LIST_HEAD(&hdev->long_term_keys);
@@ -4036,6 +4064,7 @@ void hci_unregister_dev(struct hci_dev *hdev)
4036 4064
4037 hci_dev_lock(hdev); 4065 hci_dev_lock(hdev);
4038 hci_bdaddr_list_clear(&hdev->blacklist); 4066 hci_bdaddr_list_clear(&hdev->blacklist);
4067 hci_bdaddr_list_clear(&hdev->whitelist);
4039 hci_uuids_clear(hdev); 4068 hci_uuids_clear(hdev);
4040 hci_link_keys_clear(hdev); 4069 hci_link_keys_clear(hdev);
4041 hci_smp_ltks_clear(hdev); 4070 hci_smp_ltks_clear(hdev);
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 592e73eea76d..49581e99685c 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -5219,7 +5219,7 @@ static int add_device(struct sock *sk, struct hci_dev *hdev,
5219 5219
5220 BT_DBG("%s", hdev->name); 5220 BT_DBG("%s", hdev->name);
5221 5221
5222 if (!bdaddr_type_is_le(cp->addr.type) || 5222 if (!bdaddr_type_is_valid(cp->addr.type) ||
5223 !bacmp(&cp->addr.bdaddr, BDADDR_ANY)) 5223 !bacmp(&cp->addr.bdaddr, BDADDR_ANY))
5224 return cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE, 5224 return cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5225 MGMT_STATUS_INVALID_PARAMS, 5225 MGMT_STATUS_INVALID_PARAMS,
@@ -5232,6 +5232,22 @@ static int add_device(struct sock *sk, struct hci_dev *hdev,
5232 5232
5233 hci_dev_lock(hdev); 5233 hci_dev_lock(hdev);
5234 5234
5235 if (cp->addr.type == BDADDR_BREDR) {
5236 /* Only "connect" action supported for now */
5237 if (cp->action != 0x01) {
5238 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5239 MGMT_STATUS_INVALID_PARAMS,
5240 &cp->addr, sizeof(cp->addr));
5241 goto unlock;
5242 }
5243
5244 err = hci_bdaddr_list_add(&hdev->whitelist, &cp->addr.bdaddr,
5245 cp->addr.type);
5246 if (err)
5247 goto unlock;
5248 goto added;
5249 }
5250
5235 if (cp->addr.type == BDADDR_LE_PUBLIC) 5251 if (cp->addr.type == BDADDR_LE_PUBLIC)
5236 addr_type = ADDR_LE_DEV_PUBLIC; 5252 addr_type = ADDR_LE_DEV_PUBLIC;
5237 else 5253 else
@@ -5253,6 +5269,7 @@ static int add_device(struct sock *sk, struct hci_dev *hdev,
5253 goto unlock; 5269 goto unlock;
5254 } 5270 }
5255 5271
5272added:
5256 device_added(sk, hdev, &cp->addr.bdaddr, cp->addr.type, cp->action); 5273 device_added(sk, hdev, &cp->addr.bdaddr, cp->addr.type, cp->action);
5257 5274
5258 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE, 5275 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
@@ -5288,13 +5305,30 @@ static int remove_device(struct sock *sk, struct hci_dev *hdev,
5288 struct hci_conn_params *params; 5305 struct hci_conn_params *params;
5289 u8 addr_type; 5306 u8 addr_type;
5290 5307
5291 if (!bdaddr_type_is_le(cp->addr.type)) { 5308 if (!bdaddr_type_is_valid(cp->addr.type)) {
5292 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE, 5309 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE,
5293 MGMT_STATUS_INVALID_PARAMS, 5310 MGMT_STATUS_INVALID_PARAMS,
5294 &cp->addr, sizeof(cp->addr)); 5311 &cp->addr, sizeof(cp->addr));
5295 goto unlock; 5312 goto unlock;
5296 } 5313 }
5297 5314
5315 if (cp->addr.type == BDADDR_BREDR) {
5316 err = hci_bdaddr_list_del(&hdev->whitelist,
5317 &cp->addr.bdaddr,
5318 cp->addr.type);
5319 if (err) {
5320 err = cmd_complete(sk, hdev->id,
5321 MGMT_OP_REMOVE_DEVICE,
5322 MGMT_STATUS_INVALID_PARAMS,
5323 &cp->addr, sizeof(cp->addr));
5324 goto unlock;
5325 }
5326
5327 device_removed(sk, hdev, &cp->addr.bdaddr,
5328 cp->addr.type);
5329 goto complete;
5330 }
5331
5298 if (cp->addr.type == BDADDR_LE_PUBLIC) 5332 if (cp->addr.type == BDADDR_LE_PUBLIC)
5299 addr_type = ADDR_LE_DEV_PUBLIC; 5333 addr_type = ADDR_LE_DEV_PUBLIC;
5300 else 5334 else
@@ -5324,6 +5358,7 @@ static int remove_device(struct sock *sk, struct hci_dev *hdev,
5324 device_removed(sk, hdev, &cp->addr.bdaddr, cp->addr.type); 5358 device_removed(sk, hdev, &cp->addr.bdaddr, cp->addr.type);
5325 } else { 5359 } else {
5326 struct hci_conn_params *p, *tmp; 5360 struct hci_conn_params *p, *tmp;
5361 struct bdaddr_list *b, *btmp;
5327 5362
5328 if (cp->addr.type) { 5363 if (cp->addr.type) {
5329 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE, 5364 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE,
@@ -5332,6 +5367,12 @@ static int remove_device(struct sock *sk, struct hci_dev *hdev,
5332 goto unlock; 5367 goto unlock;
5333 } 5368 }
5334 5369
5370 list_for_each_entry_safe(b, btmp, &hdev->whitelist, list) {
5371 device_removed(sk, hdev, &b->bdaddr, b->bdaddr_type);
5372 list_del(&b->list);
5373 kfree(b);
5374 }
5375
5335 list_for_each_entry_safe(p, tmp, &hdev->le_conn_params, list) { 5376 list_for_each_entry_safe(p, tmp, &hdev->le_conn_params, list) {
5336 if (p->auto_connect == HCI_AUTO_CONN_DISABLED) 5377 if (p->auto_connect == HCI_AUTO_CONN_DISABLED)
5337 continue; 5378 continue;
@@ -5346,6 +5387,7 @@ static int remove_device(struct sock *sk, struct hci_dev *hdev,
5346 hci_update_background_scan(hdev); 5387 hci_update_background_scan(hdev);
5347 } 5388 }
5348 5389
5390complete:
5349 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE, 5391 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE,
5350 MGMT_STATUS_SUCCESS, &cp->addr, sizeof(cp->addr)); 5392 MGMT_STATUS_SUCCESS, &cp->addr, sizeof(cp->addr));
5351 5393