summaryrefslogtreecommitdiff
path: root/net
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2016-03-14 19:44:56 (GMT)
committerDavid S. Miller <davem@davemloft.net>2016-03-14 19:44:56 (GMT)
commit180a2c542ce904e256ba0d8732517d7f42b3f3fa (patch)
treeca2f16af1ef73587ffd9bd0b116aeaa24c21125e /net
parentf7f58ae0f81bf454030eb76444646d15b0bfba2c (diff)
parent6a0e78072c2ae7b20b14e0249d8108441ea928d2 (diff)
downloadlinux-180a2c542ce904e256ba0d8732517d7f42b3f3fa.tar.xz
Merge branch 'for-upstream' of git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth-next
Johan Hedberg says: ==================== pull request: bluetooth-next 2016-03-12 Here's the last bluetooth-next pull request for the 4.6 kernel. - New USB ID for AR3012 in btusb - New BCM2E55 ACPI ID - Buffer overflow fix for the Add Advertising command - Support for a new Bluetooth LE limited privacy mode - Fix for firmware activation in btmrvl_sdio - Cleanups to mac802154 & 6lowpan code Please let me know if there are any issues pulling. Thanks. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r--net/6lowpan/debugfs.c4
-rw-r--r--net/6lowpan/iphc.c4
-rw-r--r--net/bluetooth/hci_conn.c17
-rw-r--r--net/bluetooth/hci_request.c56
-rw-r--r--net/bluetooth/hci_request.h2
-rw-r--r--net/bluetooth/mgmt.c26
6 files changed, 91 insertions, 18 deletions
diff --git a/net/6lowpan/debugfs.c b/net/6lowpan/debugfs.c
index aa49ff4..0793a81 100644
--- a/net/6lowpan/debugfs.c
+++ b/net/6lowpan/debugfs.c
@@ -161,7 +161,7 @@ out:
return status;
}
-const struct file_operations lowpan_ctx_pfx_fops = {
+static const struct file_operations lowpan_ctx_pfx_fops = {
.open = lowpan_ctx_pfx_open,
.read = seq_read,
.write = lowpan_ctx_pfx_write,
@@ -238,7 +238,7 @@ static int lowpan_context_open(struct inode *inode, struct file *file)
return single_open(file, lowpan_context_show, inode->i_private);
}
-const struct file_operations lowpan_context_fops = {
+static const struct file_operations lowpan_context_fops = {
.open = lowpan_context_open,
.read = seq_read,
.llseek = seq_lseek,
diff --git a/net/6lowpan/iphc.c b/net/6lowpan/iphc.c
index 7217251..99bb22a 100644
--- a/net/6lowpan/iphc.c
+++ b/net/6lowpan/iphc.c
@@ -788,7 +788,7 @@ static u8 lowpan_compress_ctx_addr(u8 **hc_ptr, const struct in6_addr *ipaddr,
}
memset(&tmp, 0, sizeof(tmp));
- /* check for SAM/DAM = 01 */
+ /* check for SAM/DAM = 10 */
tmp.s6_addr[11] = 0xFF;
tmp.s6_addr[12] = 0xFE;
memcpy(&tmp.s6_addr[14], &ipaddr->s6_addr[14], 2);
@@ -801,7 +801,7 @@ static u8 lowpan_compress_ctx_addr(u8 **hc_ptr, const struct in6_addr *ipaddr,
}
memset(&tmp, 0, sizeof(tmp));
- /* check for SAM/DAM = 10, should always match */
+ /* check for SAM/DAM = 01, should always match */
memcpy(&tmp.s6_addr[8], &ipaddr->s6_addr[8], 8);
/* context information are always used */
ipv6_addr_prefix_copy(&tmp, &ctx->pfx, ctx->plen);
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
index 32575b4..bf9f8a8 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -719,6 +719,13 @@ done:
hci_dev_unlock(hdev);
}
+static bool conn_use_rpa(struct hci_conn *conn)
+{
+ struct hci_dev *hdev = conn->hdev;
+
+ return hci_dev_test_flag(hdev, HCI_PRIVACY);
+}
+
static void hci_req_add_le_create_conn(struct hci_request *req,
struct hci_conn *conn)
{
@@ -726,14 +733,15 @@ static void hci_req_add_le_create_conn(struct hci_request *req,
struct hci_dev *hdev = conn->hdev;
u8 own_addr_type;
- memset(&cp, 0, sizeof(cp));
-
/* Update random address, but set require_privacy to false so
* that we never connect with an non-resolvable address.
*/
- if (hci_update_random_address(req, false, &own_addr_type))
+ if (hci_update_random_address(req, false, conn_use_rpa(conn),
+ &own_addr_type))
return;
+ memset(&cp, 0, sizeof(cp));
+
/* Set window to be the same value as the interval to enable
* continuous scanning.
*/
@@ -774,7 +782,8 @@ static void hci_req_directed_advertising(struct hci_request *req,
/* Set require_privacy to false so that the remote device has a
* chance of identifying us.
*/
- if (hci_update_random_address(req, false, &own_addr_type) < 0)
+ if (hci_update_random_address(req, false, conn_use_rpa(conn),
+ &own_addr_type) < 0)
return;
memset(&cp, 0, sizeof(cp));
diff --git a/net/bluetooth/hci_request.c b/net/bluetooth/hci_request.c
index c78ee2d..6e125d7 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)
return 0x01;
}
+static bool scan_use_rpa(struct hci_dev *hdev)
+{
+ return hci_dev_test_flag(hdev, HCI_PRIVACY);
+}
+
void hci_req_add_le_passive_scan(struct hci_request *req)
{
struct hci_cp_le_set_scan_param param_cp;
@@ -785,7 +790,8 @@ void hci_req_add_le_passive_scan(struct hci_request *req)
* advertising with our address will be correctly reported
* by the controller.
*/
- if (hci_update_random_address(req, false, &own_addr_type))
+ if (hci_update_random_address(req, false, scan_use_rpa(hdev),
+ &own_addr_type))
return;
/* Adding or removing entries from the white list must
@@ -866,6 +872,11 @@ static u32 get_adv_instance_flags(struct hci_dev *hdev, u8 instance)
if (hci_dev_test_flag(hdev, HCI_ADVERTISING_CONNECTABLE))
flags |= MGMT_ADV_FLAG_CONNECTABLE;
+ if (hci_dev_test_flag(hdev, HCI_LIMITED_DISCOVERABLE))
+ flags |= MGMT_ADV_FLAG_LIMITED_DISCOV;
+ else if (hci_dev_test_flag(hdev, HCI_DISCOVERABLE))
+ flags |= MGMT_ADV_FLAG_DISCOV;
+
return flags;
}
@@ -878,6 +889,29 @@ static u32 get_adv_instance_flags(struct hci_dev *hdev, u8 instance)
return adv_instance->flags;
}
+static bool adv_use_rpa(struct hci_dev *hdev, uint32_t flags)
+{
+ /* If privacy is not enabled don't use RPA */
+ if (!hci_dev_test_flag(hdev, HCI_PRIVACY))
+ return false;
+
+ /* If basic privacy mode is enabled use RPA */
+ if (!hci_dev_test_flag(hdev, HCI_LIMITED_PRIVACY))
+ return true;
+
+ /* If limited privacy mode is enabled don't use RPA if we're
+ * both discoverable and bondable.
+ */
+ if ((flags & MGMT_ADV_FLAG_DISCOV) &&
+ hci_dev_test_flag(hdev, HCI_BONDABLE))
+ return false;
+
+ /* We're neither bondable nor discoverable in the limited
+ * privacy mode, therefore use RPA.
+ */
+ return true;
+}
+
void __hci_req_enable_advertising(struct hci_request *req)
{
struct hci_dev *hdev = req->hdev;
@@ -911,7 +945,9 @@ void __hci_req_enable_advertising(struct hci_request *req)
* advertising is used. In that case it is fine to use a
* non-resolvable private address.
*/
- if (hci_update_random_address(req, !connectable, &own_addr_type) < 0)
+ if (hci_update_random_address(req, !connectable,
+ adv_use_rpa(hdev, flags),
+ &own_addr_type) < 0)
return;
memset(&cp, 0, sizeof(cp));
@@ -1325,7 +1361,7 @@ static void set_random_addr(struct hci_request *req, bdaddr_t *rpa)
}
int hci_update_random_address(struct hci_request *req, bool require_privacy,
- u8 *own_addr_type)
+ bool use_rpa, u8 *own_addr_type)
{
struct hci_dev *hdev = req->hdev;
int err;
@@ -1334,7 +1370,7 @@ int hci_update_random_address(struct hci_request *req, bool require_privacy,
* current RPA has expired or there is something else than
* the current RPA in use, then generate a new one.
*/
- if (hci_dev_test_flag(hdev, HCI_PRIVACY)) {
+ if (use_rpa) {
int to;
*own_addr_type = ADDR_LE_DEV_RANDOM;
@@ -1596,9 +1632,16 @@ static int discoverable_update(struct hci_request *req, unsigned long opt)
/* Advertising instances don't use the global discoverable setting, so
* only update AD if advertising was enabled using Set Advertising.
*/
- if (hci_dev_test_flag(hdev, HCI_ADVERTISING))
+ if (hci_dev_test_flag(hdev, HCI_ADVERTISING)) {
__hci_req_update_adv_data(req, 0x00);
+ /* Discoverable mode affects the local advertising
+ * address in limited privacy mode.
+ */
+ if (hci_dev_test_flag(hdev, HCI_LIMITED_PRIVACY))
+ __hci_req_enable_advertising(req);
+ }
+
hci_dev_unlock(hdev);
return 0;
@@ -1941,7 +1984,8 @@ static int active_scan(struct hci_request *req, unsigned long opt)
* address (when privacy feature has been enabled) or non-resolvable
* private address.
*/
- err = hci_update_random_address(req, true, &own_addr_type);
+ err = hci_update_random_address(req, true, scan_use_rpa(hdev),
+ &own_addr_type);
if (err < 0)
own_addr_type = ADDR_LE_DEV_PUBLIC;
diff --git a/net/bluetooth/hci_request.h b/net/bluetooth/hci_request.h
index 64ff8c0..b2d044b 100644
--- a/net/bluetooth/hci_request.h
+++ b/net/bluetooth/hci_request.h
@@ -89,7 +89,7 @@ static inline void hci_req_update_scan(struct hci_dev *hdev)
void __hci_req_update_scan(struct hci_request *req);
int hci_update_random_address(struct hci_request *req, bool require_privacy,
- u8 *own_addr_type);
+ bool use_rpa, u8 *own_addr_type);
int hci_abort_conn(struct hci_conn *conn, u8 reason);
void __hci_abort_conn(struct hci_request *req, struct hci_conn *conn,
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 5a5089c..9e4b931 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -38,7 +38,7 @@
#include "mgmt_util.h"
#define MGMT_VERSION 1
-#define MGMT_REVISION 11
+#define MGMT_REVISION 12
static const u16 mgmt_commands[] = {
MGMT_OP_READ_INDEX_LIST,
@@ -1382,8 +1382,19 @@ static int set_bondable(struct sock *sk, struct hci_dev *hdev, void *data,
if (err < 0)
goto unlock;
- if (changed)
+ if (changed) {
+ /* In limited privacy mode the change of bondable mode
+ * may affect the local advertising address.
+ */
+ if (hdev_is_powered(hdev) &&
+ hci_dev_test_flag(hdev, HCI_ADVERTISING) &&
+ hci_dev_test_flag(hdev, HCI_DISCOVERABLE) &&
+ hci_dev_test_flag(hdev, HCI_LIMITED_PRIVACY))
+ queue_work(hdev->req_workqueue,
+ &hdev->discoverable_update);
+
err = new_settings(hdev, sk);
+ }
unlock:
hci_dev_unlock(hdev);
@@ -4423,7 +4434,7 @@ static int set_privacy(struct sock *sk, struct hci_dev *hdev, void *cp_data,
return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
MGMT_STATUS_NOT_SUPPORTED);
- if (cp->privacy != 0x00 && cp->privacy != 0x01)
+ if (cp->privacy != 0x00 && cp->privacy != 0x01 && cp->privacy != 0x02)
return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
MGMT_STATUS_INVALID_PARAMS);
@@ -4442,10 +4453,15 @@ static int set_privacy(struct sock *sk, struct hci_dev *hdev, void *cp_data,
changed = !hci_dev_test_and_set_flag(hdev, HCI_PRIVACY);
memcpy(hdev->irk, cp->irk, sizeof(hdev->irk));
hci_dev_set_flag(hdev, HCI_RPA_EXPIRED);
+ if (cp->privacy == 0x02)
+ hci_dev_set_flag(hdev, HCI_LIMITED_PRIVACY);
+ else
+ hci_dev_clear_flag(hdev, HCI_LIMITED_PRIVACY);
} else {
changed = hci_dev_test_and_clear_flag(hdev, HCI_PRIVACY);
memset(hdev->irk, 0, sizeof(hdev->irk));
hci_dev_clear_flag(hdev, HCI_RPA_EXPIRED);
+ hci_dev_clear_flag(hdev, HCI_LIMITED_PRIVACY);
}
err = send_settings_rsp(sk, MGMT_OP_SET_PRIVACY, hdev);
@@ -5979,6 +5995,10 @@ static int add_advertising(struct sock *sk, struct hci_dev *hdev,
return mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_ADVERTISING,
MGMT_STATUS_INVALID_PARAMS);
+ if (data_len != sizeof(*cp) + cp->adv_data_len + cp->scan_rsp_len)
+ return mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_ADVERTISING,
+ MGMT_STATUS_INVALID_PARAMS);
+
flags = __le32_to_cpu(cp->flags);
timeout = __le16_to_cpu(cp->timeout);
duration = __le16_to_cpu(cp->duration);