diff options
author | Johan Hedberg <johan.hedberg@intel.com> | 2016-03-09 10:30:34 -0500 |
---|---|---|
committer | Marcel Holtmann <marcel@holtmann.org> | 2016-03-10 13:51:30 -0500 |
commit | 82a37adeedd38880940e2772ec1ae27a09353e5a (patch) | |
tree | 1bcb7b13da9a469b99334e01090ea23bc62d29af /net/bluetooth/hci_request.c | |
parent | d43efbd0d545f476be0bbef30cbe18234f8a9631 (diff) |
Bluetooth: Add support for limited privacy mode
Introduce a limited privacy mode indicated by value 0x02 to the mgmt
Set Privacy command.
With value 0x02 the kernel will use privacy mode with a resolvable
private address. In case the controller is bondable and discoverable
the identity address will be used.
Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
Diffstat (limited to 'net/bluetooth/hci_request.c')
-rw-r--r-- | net/bluetooth/hci_request.c | 51 |
1 files changed, 45 insertions, 6 deletions
diff --git a/net/bluetooth/hci_request.c b/net/bluetooth/hci_request.c index 77be344efd18..95a545ca9dbc 100644 --- a/net/bluetooth/hci_request.c +++ b/net/bluetooth/hci_request.c | |||
@@ -771,6 +771,11 @@ static u8 update_white_list(struct hci_request *req) | |||
771 | return 0x01; | 771 | return 0x01; |
772 | } | 772 | } |
773 | 773 | ||
774 | static bool scan_use_rpa(struct hci_dev *hdev) | ||
775 | { | ||
776 | return hci_dev_test_flag(hdev, HCI_PRIVACY); | ||
777 | } | ||
778 | |||
774 | void hci_req_add_le_passive_scan(struct hci_request *req) | 779 | void hci_req_add_le_passive_scan(struct hci_request *req) |
775 | { | 780 | { |
776 | struct hci_cp_le_set_scan_param param_cp; | 781 | struct hci_cp_le_set_scan_param param_cp; |
@@ -785,7 +790,8 @@ void hci_req_add_le_passive_scan(struct hci_request *req) | |||
785 | * advertising with our address will be correctly reported | 790 | * advertising with our address will be correctly reported |
786 | * by the controller. | 791 | * by the controller. |
787 | */ | 792 | */ |
788 | if (hci_update_random_address(req, false, &own_addr_type)) | 793 | if (hci_update_random_address(req, false, scan_use_rpa(hdev), |
794 | &own_addr_type)) | ||
789 | return; | 795 | return; |
790 | 796 | ||
791 | /* Adding or removing entries from the white list must | 797 | /* Adding or removing entries from the white list must |
@@ -881,6 +887,29 @@ static u32 get_adv_instance_flags(struct hci_dev *hdev, u8 instance) | |||
881 | return adv_instance->flags; | 887 | return adv_instance->flags; |
882 | } | 888 | } |
883 | 889 | ||
890 | static bool adv_use_rpa(struct hci_dev *hdev, uint32_t flags) | ||
891 | { | ||
892 | /* If privacy is not enabled don't use RPA */ | ||
893 | if (!hci_dev_test_flag(hdev, HCI_PRIVACY)) | ||
894 | return false; | ||
895 | |||
896 | /* If basic privacy mode is enabled use RPA */ | ||
897 | if (!hci_dev_test_flag(hdev, HCI_LIMITED_PRIVACY)) | ||
898 | return true; | ||
899 | |||
900 | /* If limited privacy mode is enabled don't use RPA if we're | ||
901 | * both discoverable and bondable. | ||
902 | */ | ||
903 | if ((flags & MGMT_ADV_FLAG_DISCOV) && | ||
904 | hci_dev_test_flag(hdev, HCI_BONDABLE)) | ||
905 | return false; | ||
906 | |||
907 | /* We're neither bondable nor discoverable in the limited | ||
908 | * privacy mode, therefore use RPA. | ||
909 | */ | ||
910 | return true; | ||
911 | } | ||
912 | |||
884 | void __hci_req_enable_advertising(struct hci_request *req) | 913 | void __hci_req_enable_advertising(struct hci_request *req) |
885 | { | 914 | { |
886 | struct hci_dev *hdev = req->hdev; | 915 | struct hci_dev *hdev = req->hdev; |
@@ -914,7 +943,9 @@ void __hci_req_enable_advertising(struct hci_request *req) | |||
914 | * advertising is used. In that case it is fine to use a | 943 | * advertising is used. In that case it is fine to use a |
915 | * non-resolvable private address. | 944 | * non-resolvable private address. |
916 | */ | 945 | */ |
917 | if (hci_update_random_address(req, !connectable, &own_addr_type) < 0) | 946 | if (hci_update_random_address(req, !connectable, |
947 | adv_use_rpa(hdev, flags), | ||
948 | &own_addr_type) < 0) | ||
918 | return; | 949 | return; |
919 | 950 | ||
920 | memset(&cp, 0, sizeof(cp)); | 951 | memset(&cp, 0, sizeof(cp)); |
@@ -1328,7 +1359,7 @@ static void set_random_addr(struct hci_request *req, bdaddr_t *rpa) | |||
1328 | } | 1359 | } |
1329 | 1360 | ||
1330 | int hci_update_random_address(struct hci_request *req, bool require_privacy, | 1361 | int hci_update_random_address(struct hci_request *req, bool require_privacy, |
1331 | u8 *own_addr_type) | 1362 | bool use_rpa, u8 *own_addr_type) |
1332 | { | 1363 | { |
1333 | struct hci_dev *hdev = req->hdev; | 1364 | struct hci_dev *hdev = req->hdev; |
1334 | int err; | 1365 | int err; |
@@ -1337,7 +1368,7 @@ int hci_update_random_address(struct hci_request *req, bool require_privacy, | |||
1337 | * current RPA has expired or there is something else than | 1368 | * current RPA has expired or there is something else than |
1338 | * the current RPA in use, then generate a new one. | 1369 | * the current RPA in use, then generate a new one. |
1339 | */ | 1370 | */ |
1340 | if (hci_dev_test_flag(hdev, HCI_PRIVACY)) { | 1371 | if (use_rpa) { |
1341 | int to; | 1372 | int to; |
1342 | 1373 | ||
1343 | *own_addr_type = ADDR_LE_DEV_RANDOM; | 1374 | *own_addr_type = ADDR_LE_DEV_RANDOM; |
@@ -1599,9 +1630,16 @@ static int discoverable_update(struct hci_request *req, unsigned long opt) | |||
1599 | /* Advertising instances don't use the global discoverable setting, so | 1630 | /* Advertising instances don't use the global discoverable setting, so |
1600 | * only update AD if advertising was enabled using Set Advertising. | 1631 | * only update AD if advertising was enabled using Set Advertising. |
1601 | */ | 1632 | */ |
1602 | if (hci_dev_test_flag(hdev, HCI_ADVERTISING)) | 1633 | if (hci_dev_test_flag(hdev, HCI_ADVERTISING)) { |
1603 | __hci_req_update_adv_data(req, 0x00); | 1634 | __hci_req_update_adv_data(req, 0x00); |
1604 | 1635 | ||
1636 | /* Discoverable mode affects the local advertising | ||
1637 | * address in limited privacy mode. | ||
1638 | */ | ||
1639 | if (hci_dev_test_flag(hdev, HCI_LIMITED_PRIVACY)) | ||
1640 | __hci_req_enable_advertising(req); | ||
1641 | } | ||
1642 | |||
1605 | hci_dev_unlock(hdev); | 1643 | hci_dev_unlock(hdev); |
1606 | 1644 | ||
1607 | return 0; | 1645 | return 0; |
@@ -1944,7 +1982,8 @@ static int active_scan(struct hci_request *req, unsigned long opt) | |||
1944 | * address (when privacy feature has been enabled) or non-resolvable | 1982 | * address (when privacy feature has been enabled) or non-resolvable |
1945 | * private address. | 1983 | * private address. |
1946 | */ | 1984 | */ |
1947 | err = hci_update_random_address(req, true, &own_addr_type); | 1985 | err = hci_update_random_address(req, true, scan_use_rpa(hdev), |
1986 | &own_addr_type); | ||
1948 | if (err < 0) | 1987 | if (err < 0) |
1949 | own_addr_type = ADDR_LE_DEV_PUBLIC; | 1988 | own_addr_type = ADDR_LE_DEV_PUBLIC; |
1950 | 1989 | ||