aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/net/bluetooth/hci_core.h2
-rw-r--r--include/net/bluetooth/mgmt.h10
-rw-r--r--net/bluetooth/hci_core.c34
-rw-r--r--net/bluetooth/hci_sock.c18
-rw-r--r--net/bluetooth/mgmt.c62
5 files changed, 92 insertions, 34 deletions
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index ee1ee1bfae9e..5b924423cf20 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -873,6 +873,8 @@ int mgmt_device_found(u16 index, bdaddr_t *bdaddr, u8 *dev_class, s8 rssi,
873 u8 *eir); 873 u8 *eir);
874int mgmt_remote_name(u16 index, bdaddr_t *bdaddr, u8 *name); 874int mgmt_remote_name(u16 index, bdaddr_t *bdaddr, u8 *name);
875int mgmt_discovering(u16 index, u8 discovering); 875int mgmt_discovering(u16 index, u8 discovering);
876int mgmt_device_blocked(u16 index, bdaddr_t *bdaddr);
877int mgmt_device_unblocked(u16 index, bdaddr_t *bdaddr);
876 878
877/* HCI info for socket */ 879/* HCI info for socket */
878#define hci_pi(sk) ((struct hci_pinfo *) sk) 880#define hci_pi(sk) ((struct hci_pinfo *) sk)
diff --git a/include/net/bluetooth/mgmt.h b/include/net/bluetooth/mgmt.h
index 48522e6386bf..d66da0f94f95 100644
--- a/include/net/bluetooth/mgmt.h
+++ b/include/net/bluetooth/mgmt.h
@@ -307,3 +307,13 @@ struct mgmt_ev_remote_name {
307} __packed; 307} __packed;
308 308
309#define MGMT_EV_DISCOVERING 0x0014 309#define MGMT_EV_DISCOVERING 0x0014
310
311#define MGMT_EV_DEVICE_BLOCKED 0x0015
312struct mgmt_ev_device_blocked {
313 bdaddr_t bdaddr;
314} __packed;
315
316#define MGMT_EV_DEVICE_UNBLOCKED 0x0016
317struct mgmt_ev_device_unblocked {
318 bdaddr_t bdaddr;
319} __packed;
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index b4e7cde35365..b84458dcc226 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -1312,59 +1312,41 @@ int hci_blacklist_clear(struct hci_dev *hdev)
1312int hci_blacklist_add(struct hci_dev *hdev, bdaddr_t *bdaddr) 1312int hci_blacklist_add(struct hci_dev *hdev, bdaddr_t *bdaddr)
1313{ 1313{
1314 struct bdaddr_list *entry; 1314 struct bdaddr_list *entry;
1315 int err;
1316 1315
1317 if (bacmp(bdaddr, BDADDR_ANY) == 0) 1316 if (bacmp(bdaddr, BDADDR_ANY) == 0)
1318 return -EBADF; 1317 return -EBADF;
1319 1318
1320 hci_dev_lock_bh(hdev); 1319 if (hci_blacklist_lookup(hdev, bdaddr))
1321 1320 return -EEXIST;
1322 if (hci_blacklist_lookup(hdev, bdaddr)) {
1323 err = -EEXIST;
1324 goto err;
1325 }
1326 1321
1327 entry = kzalloc(sizeof(struct bdaddr_list), GFP_KERNEL); 1322 entry = kzalloc(sizeof(struct bdaddr_list), GFP_KERNEL);
1328 if (!entry) { 1323 if (!entry)
1329 err = -ENOMEM; 1324 return -ENOMEM;
1330 goto err;
1331 }
1332 1325
1333 bacpy(&entry->bdaddr, bdaddr); 1326 bacpy(&entry->bdaddr, bdaddr);
1334 1327
1335 list_add(&entry->list, &hdev->blacklist); 1328 list_add(&entry->list, &hdev->blacklist);
1336 1329
1337 err = 0; 1330 return mgmt_device_blocked(hdev->id, bdaddr);
1338
1339err:
1340 hci_dev_unlock_bh(hdev);
1341 return err;
1342} 1331}
1343 1332
1344int hci_blacklist_del(struct hci_dev *hdev, bdaddr_t *bdaddr) 1333int hci_blacklist_del(struct hci_dev *hdev, bdaddr_t *bdaddr)
1345{ 1334{
1346 struct bdaddr_list *entry; 1335 struct bdaddr_list *entry;
1347 int err = 0;
1348
1349 hci_dev_lock_bh(hdev);
1350 1336
1351 if (bacmp(bdaddr, BDADDR_ANY) == 0) { 1337 if (bacmp(bdaddr, BDADDR_ANY) == 0) {
1352 hci_blacklist_clear(hdev); 1338 return hci_blacklist_clear(hdev);
1353 goto done;
1354 } 1339 }
1355 1340
1356 entry = hci_blacklist_lookup(hdev, bdaddr); 1341 entry = hci_blacklist_lookup(hdev, bdaddr);
1357 if (!entry) { 1342 if (!entry) {
1358 err = -ENOENT; 1343 return -ENOENT;
1359 goto done;
1360 } 1344 }
1361 1345
1362 list_del(&entry->list); 1346 list_del(&entry->list);
1363 kfree(entry); 1347 kfree(entry);
1364 1348
1365done: 1349 return mgmt_device_unblocked(hdev->id, bdaddr);
1366 hci_dev_unlock_bh(hdev);
1367 return err;
1368} 1350}
1369 1351
1370static void hci_clear_adv_cache(unsigned long arg) 1352static void hci_clear_adv_cache(unsigned long arg)
diff --git a/net/bluetooth/hci_sock.c b/net/bluetooth/hci_sock.c
index ff02cf5e77cc..f6afe3d76a66 100644
--- a/net/bluetooth/hci_sock.c
+++ b/net/bluetooth/hci_sock.c
@@ -183,21 +183,35 @@ static int hci_sock_release(struct socket *sock)
183static int hci_sock_blacklist_add(struct hci_dev *hdev, void __user *arg) 183static int hci_sock_blacklist_add(struct hci_dev *hdev, void __user *arg)
184{ 184{
185 bdaddr_t bdaddr; 185 bdaddr_t bdaddr;
186 int err;
186 187
187 if (copy_from_user(&bdaddr, arg, sizeof(bdaddr))) 188 if (copy_from_user(&bdaddr, arg, sizeof(bdaddr)))
188 return -EFAULT; 189 return -EFAULT;
189 190
190 return hci_blacklist_add(hdev, &bdaddr); 191 hci_dev_lock_bh(hdev);
192
193 err = hci_blacklist_add(hdev, &bdaddr);
194
195 hci_dev_unlock_bh(hdev);
196
197 return err;
191} 198}
192 199
193static int hci_sock_blacklist_del(struct hci_dev *hdev, void __user *arg) 200static int hci_sock_blacklist_del(struct hci_dev *hdev, void __user *arg)
194{ 201{
195 bdaddr_t bdaddr; 202 bdaddr_t bdaddr;
203 int err;
196 204
197 if (copy_from_user(&bdaddr, arg, sizeof(bdaddr))) 205 if (copy_from_user(&bdaddr, arg, sizeof(bdaddr)))
198 return -EFAULT; 206 return -EFAULT;
199 207
200 return hci_blacklist_del(hdev, &bdaddr); 208 hci_dev_lock_bh(hdev);
209
210 err = hci_blacklist_del(hdev, &bdaddr);
211
212 hci_dev_unlock_bh(hdev);
213
214 return err;
201} 215}
202 216
203/* Ioctls that require bound socket */ 217/* Ioctls that require bound socket */
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 6493e807634f..579f7261a7fe 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -1698,13 +1698,12 @@ static int block_device(struct sock *sk, u16 index, unsigned char *data,
1698 u16 len) 1698 u16 len)
1699{ 1699{
1700 struct hci_dev *hdev; 1700 struct hci_dev *hdev;
1701 struct mgmt_cp_block_device *cp; 1701 struct pending_cmd *cmd;
1702 struct mgmt_cp_block_device *cp = (void *) data;
1702 int err; 1703 int err;
1703 1704
1704 BT_DBG("hci%u", index); 1705 BT_DBG("hci%u", index);
1705 1706
1706 cp = (void *) data;
1707
1708 if (len != sizeof(*cp)) 1707 if (len != sizeof(*cp))
1709 return cmd_status(sk, index, MGMT_OP_BLOCK_DEVICE, 1708 return cmd_status(sk, index, MGMT_OP_BLOCK_DEVICE,
1710 EINVAL); 1709 EINVAL);
@@ -1714,6 +1713,14 @@ static int block_device(struct sock *sk, u16 index, unsigned char *data,
1714 return cmd_status(sk, index, MGMT_OP_BLOCK_DEVICE, 1713 return cmd_status(sk, index, MGMT_OP_BLOCK_DEVICE,
1715 ENODEV); 1714 ENODEV);
1716 1715
1716 hci_dev_lock_bh(hdev);
1717
1718 cmd = mgmt_pending_add(sk, MGMT_OP_BLOCK_DEVICE, index, NULL, 0);
1719 if (!cmd) {
1720 err = -ENOMEM;
1721 goto failed;
1722 }
1723
1717 err = hci_blacklist_add(hdev, &cp->bdaddr); 1724 err = hci_blacklist_add(hdev, &cp->bdaddr);
1718 1725
1719 if (err < 0) 1726 if (err < 0)
@@ -1721,6 +1728,11 @@ static int block_device(struct sock *sk, u16 index, unsigned char *data,
1721 else 1728 else
1722 err = cmd_complete(sk, index, MGMT_OP_BLOCK_DEVICE, 1729 err = cmd_complete(sk, index, MGMT_OP_BLOCK_DEVICE,
1723 NULL, 0); 1730 NULL, 0);
1731
1732 mgmt_pending_remove(cmd);
1733
1734failed:
1735 hci_dev_unlock_bh(hdev);
1724 hci_dev_put(hdev); 1736 hci_dev_put(hdev);
1725 1737
1726 return err; 1738 return err;
@@ -1730,13 +1742,12 @@ static int unblock_device(struct sock *sk, u16 index, unsigned char *data,
1730 u16 len) 1742 u16 len)
1731{ 1743{
1732 struct hci_dev *hdev; 1744 struct hci_dev *hdev;
1733 struct mgmt_cp_unblock_device *cp; 1745 struct pending_cmd *cmd;
1746 struct mgmt_cp_unblock_device *cp = (void *) data;
1734 int err; 1747 int err;
1735 1748
1736 BT_DBG("hci%u", index); 1749 BT_DBG("hci%u", index);
1737 1750
1738 cp = (void *) data;
1739
1740 if (len != sizeof(*cp)) 1751 if (len != sizeof(*cp))
1741 return cmd_status(sk, index, MGMT_OP_UNBLOCK_DEVICE, 1752 return cmd_status(sk, index, MGMT_OP_UNBLOCK_DEVICE,
1742 EINVAL); 1753 EINVAL);
@@ -1746,6 +1757,14 @@ static int unblock_device(struct sock *sk, u16 index, unsigned char *data,
1746 return cmd_status(sk, index, MGMT_OP_UNBLOCK_DEVICE, 1757 return cmd_status(sk, index, MGMT_OP_UNBLOCK_DEVICE,
1747 ENODEV); 1758 ENODEV);
1748 1759
1760 hci_dev_lock_bh(hdev);
1761
1762 cmd = mgmt_pending_add(sk, MGMT_OP_UNBLOCK_DEVICE, index, NULL, 0);
1763 if (!cmd) {
1764 err = -ENOMEM;
1765 goto failed;
1766 }
1767
1749 err = hci_blacklist_del(hdev, &cp->bdaddr); 1768 err = hci_blacklist_del(hdev, &cp->bdaddr);
1750 1769
1751 if (err < 0) 1770 if (err < 0)
@@ -1753,6 +1772,11 @@ static int unblock_device(struct sock *sk, u16 index, unsigned char *data,
1753 else 1772 else
1754 err = cmd_complete(sk, index, MGMT_OP_UNBLOCK_DEVICE, 1773 err = cmd_complete(sk, index, MGMT_OP_UNBLOCK_DEVICE,
1755 NULL, 0); 1774 NULL, 0);
1775
1776 mgmt_pending_remove(cmd);
1777
1778failed:
1779 hci_dev_unlock_bh(hdev);
1756 hci_dev_put(hdev); 1780 hci_dev_put(hdev);
1757 1781
1758 return err; 1782 return err;
@@ -2356,3 +2380,29 @@ int mgmt_discovering(u16 index, u8 discovering)
2356 return mgmt_event(MGMT_EV_DISCOVERING, index, &discovering, 2380 return mgmt_event(MGMT_EV_DISCOVERING, index, &discovering,
2357 sizeof(discovering), NULL); 2381 sizeof(discovering), NULL);
2358} 2382}
2383
2384int mgmt_device_blocked(u16 index, bdaddr_t *bdaddr)
2385{
2386 struct pending_cmd *cmd;
2387 struct mgmt_ev_device_blocked ev;
2388
2389 cmd = mgmt_pending_find(MGMT_OP_BLOCK_DEVICE, index);
2390
2391 bacpy(&ev.bdaddr, bdaddr);
2392
2393 return mgmt_event(MGMT_EV_DEVICE_BLOCKED, index, &ev, sizeof(ev),
2394 cmd ? cmd->sk : NULL);
2395}
2396
2397int mgmt_device_unblocked(u16 index, bdaddr_t *bdaddr)
2398{
2399 struct pending_cmd *cmd;
2400 struct mgmt_ev_device_unblocked ev;
2401
2402 cmd = mgmt_pending_find(MGMT_OP_UNBLOCK_DEVICE, index);
2403
2404 bacpy(&ev.bdaddr, bdaddr);
2405
2406 return mgmt_event(MGMT_EV_DEVICE_UNBLOCKED, index, &ev, sizeof(ev),
2407 cmd ? cmd->sk : NULL);
2408}