diff options
-rw-r--r-- | include/net/bluetooth/hci_core.h | 2 | ||||
-rw-r--r-- | include/net/bluetooth/mgmt.h | 10 | ||||
-rw-r--r-- | net/bluetooth/hci_core.c | 34 | ||||
-rw-r--r-- | net/bluetooth/hci_sock.c | 18 | ||||
-rw-r--r-- | net/bluetooth/mgmt.c | 62 |
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); |
874 | int mgmt_remote_name(u16 index, bdaddr_t *bdaddr, u8 *name); | 874 | int mgmt_remote_name(u16 index, bdaddr_t *bdaddr, u8 *name); |
875 | int mgmt_discovering(u16 index, u8 discovering); | 875 | int mgmt_discovering(u16 index, u8 discovering); |
876 | int mgmt_device_blocked(u16 index, bdaddr_t *bdaddr); | ||
877 | int 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 | ||
312 | struct mgmt_ev_device_blocked { | ||
313 | bdaddr_t bdaddr; | ||
314 | } __packed; | ||
315 | |||
316 | #define MGMT_EV_DEVICE_UNBLOCKED 0x0016 | ||
317 | struct 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) | |||
1312 | int hci_blacklist_add(struct hci_dev *hdev, bdaddr_t *bdaddr) | 1312 | int 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 | |||
1339 | err: | ||
1340 | hci_dev_unlock_bh(hdev); | ||
1341 | return err; | ||
1342 | } | 1331 | } |
1343 | 1332 | ||
1344 | int hci_blacklist_del(struct hci_dev *hdev, bdaddr_t *bdaddr) | 1333 | int 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 | ||
1365 | done: | 1349 | return mgmt_device_unblocked(hdev->id, bdaddr); |
1366 | hci_dev_unlock_bh(hdev); | ||
1367 | return err; | ||
1368 | } | 1350 | } |
1369 | 1351 | ||
1370 | static void hci_clear_adv_cache(unsigned long arg) | 1352 | static 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) | |||
183 | static int hci_sock_blacklist_add(struct hci_dev *hdev, void __user *arg) | 183 | static 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 | ||
193 | static int hci_sock_blacklist_del(struct hci_dev *hdev, void __user *arg) | 200 | static 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 | |||
1734 | failed: | ||
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 | |||
1778 | failed: | ||
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 | |||
2384 | int 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 | |||
2397 | int 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 | } | ||