aboutsummaryrefslogtreecommitdiffstats
path: root/net/bluetooth
diff options
context:
space:
mode:
authorAntti Julku <antti.julku@nokia.com>2011-08-25 09:48:02 -0400
committerGustavo F. Padovan <padovan@profusion.mobi>2011-09-21 11:59:15 -0400
commit5e762444b0d3e56bbd66f5092434c4a1ba698313 (patch)
treead54379252e2fa923a3001a1c194ef541a87a686 /net/bluetooth
parentc908df362c20be0eeef506fe62e13d835a4633f9 (diff)
Bluetooth: Add mgmt events for blacklisting
Add management interface events for blocking/unblocking a device. Sender of the block device command gets cmd complete and other mgmt sockets get the event. Event is also sent to mgmt sockets when blocking is done with ioctl, e.g when blocking a device with hciconfig. This makes it possible for bluetoothd to track status of blocked devices when a third party block or unblocks a device. Event sending is handled in mgmt_device_blocked function which gets called from hci_blacklist_add in hci_core.c. A pending command is added in mgmt_block_device, so that it can found when sending the event - the event is not sent to the socket from which the pending command came. Locks were moved out from hci_core.c to hci_sock.c and mgmt.c, because locking is needed also for mgmt_pending_add in mgmt.c. Signed-off-by: Antti Julku <antti.julku@nokia.com> Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi>
Diffstat (limited to 'net/bluetooth')
-rw-r--r--net/bluetooth/hci_core.c34
-rw-r--r--net/bluetooth/hci_sock.c18
-rw-r--r--net/bluetooth/mgmt.c62
3 files changed, 80 insertions, 34 deletions
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}