aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarcel Holtmann <marcel@holtmann.org>2013-10-02 07:41:30 -0400
committerJohan Hedberg <johan.hedberg@intel.com>2013-10-02 07:50:58 -0400
commitd13eafce2c892d57f1eb243e43dfe48b4626006d (patch)
tree6ce6e6a461756a0a5a5e7371b77a60f1977b7a10
parenta0cdf960bec0b040307229bc25c40fa33c20dff1 (diff)
Bluetooth: Add management command for setting static address
On dual-mode BR/EDR/LE and LE only controllers it is possible to configure a random address. There are two types or random addresses, one is static and the other private. Since the random private addresses require special privacy feature to be supported, the configuration of these two are kept separate. This command allows for setting the static random address. It is only supported on controllers with LE support. The static random address is suppose to be valid for the lifetime of the controller or at least until the next power cycle. To ensure such behavior, setting of the address is limited to when the controller is powered off. The special BDADDR_ANY address (00:00:00:00:00:00) can be used to disable the static address. This is also the default value. Signed-off-by: Marcel Holtmann <marcel@holtmann.org> Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
-rw-r--r--include/net/bluetooth/hci.h2
-rw-r--r--include/net/bluetooth/hci_core.h1
-rw-r--r--include/net/bluetooth/mgmt.h6
-rw-r--r--net/bluetooth/mgmt.c49
4 files changed, 58 insertions, 0 deletions
diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index 4fa08d7b997d..d7fd825ed2ce 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -978,6 +978,8 @@ struct hci_rp_le_read_local_features {
978 __u8 features[8]; 978 __u8 features[8];
979} __packed; 979} __packed;
980 980
981#define HCI_OP_LE_SET_RANDOM_ADDR 0x2005
982
981#define HCI_OP_LE_READ_ADV_TX_POWER 0x2007 983#define HCI_OP_LE_READ_ADV_TX_POWER 0x2007
982struct hci_rp_le_read_adv_tx_power { 984struct hci_rp_le_read_adv_tx_power {
983 __u8 status; 985 __u8 status;
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 26cc9f7858cd..e09c30577b3a 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -140,6 +140,7 @@ struct hci_dev {
140 __u8 bus; 140 __u8 bus;
141 __u8 dev_type; 141 __u8 dev_type;
142 bdaddr_t bdaddr; 142 bdaddr_t bdaddr;
143 bdaddr_t static_addr;
143 __u8 dev_name[HCI_MAX_NAME_LENGTH]; 144 __u8 dev_name[HCI_MAX_NAME_LENGTH];
144 __u8 short_name[HCI_MAX_SHORT_NAME_LENGTH]; 145 __u8 short_name[HCI_MAX_SHORT_NAME_LENGTH];
145 __u8 eir[HCI_MAX_EIR_LENGTH]; 146 __u8 eir[HCI_MAX_EIR_LENGTH];
diff --git a/include/net/bluetooth/mgmt.h b/include/net/bluetooth/mgmt.h
index 7347df800a2e..2ad433bb9a2e 100644
--- a/include/net/bluetooth/mgmt.h
+++ b/include/net/bluetooth/mgmt.h
@@ -356,6 +356,12 @@ struct mgmt_cp_set_device_id {
356 356
357#define MGMT_OP_SET_BREDR 0x002A 357#define MGMT_OP_SET_BREDR 0x002A
358 358
359#define MGMT_OP_SET_STATIC_ADDRESS 0x002B
360struct mgmt_cp_set_static_address {
361 bdaddr_t bdaddr;
362} __packed;
363#define MGMT_SET_STATIC_ADDRESS_SIZE 6
364
359#define MGMT_EV_CMD_COMPLETE 0x0001 365#define MGMT_EV_CMD_COMPLETE 0x0001
360struct mgmt_ev_cmd_complete { 366struct mgmt_ev_cmd_complete {
361 __le16 opcode; 367 __le16 opcode;
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 4ac31695946b..b87163238c10 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -76,6 +76,7 @@ static const u16 mgmt_commands[] = {
76 MGMT_OP_SET_DEVICE_ID, 76 MGMT_OP_SET_DEVICE_ID,
77 MGMT_OP_SET_ADVERTISING, 77 MGMT_OP_SET_ADVERTISING,
78 MGMT_OP_SET_BREDR, 78 MGMT_OP_SET_BREDR,
79 MGMT_OP_SET_STATIC_ADDRESS,
79}; 80};
80 81
81static const u16 mgmt_events[] = { 82static const u16 mgmt_events[] = {
@@ -3247,6 +3248,46 @@ unlock:
3247 return err; 3248 return err;
3248} 3249}
3249 3250
3251static int set_static_address(struct sock *sk, struct hci_dev *hdev,
3252 void *data, u16 len)
3253{
3254 struct mgmt_cp_set_static_address *cp = data;
3255 int err;
3256
3257 BT_DBG("%s", hdev->name);
3258
3259 if (!lmp_le_capable(hdev))
3260 return cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS,
3261 MGMT_STATUS_NOT_SUPPORTED);
3262
3263 if (hdev_is_powered(hdev))
3264 return cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS,
3265 MGMT_STATUS_REJECTED);
3266
3267 if (bacmp(&cp->bdaddr, BDADDR_ANY)) {
3268 if (!bacmp(&cp->bdaddr, BDADDR_NONE))
3269 return cmd_status(sk, hdev->id,
3270 MGMT_OP_SET_STATIC_ADDRESS,
3271 MGMT_STATUS_INVALID_PARAMS);
3272
3273 /* Two most significant bits shall be set */
3274 if ((cp->bdaddr.b[5] & 0xc0) != 0xc0)
3275 return cmd_status(sk, hdev->id,
3276 MGMT_OP_SET_STATIC_ADDRESS,
3277 MGMT_STATUS_INVALID_PARAMS);
3278 }
3279
3280 hci_dev_lock(hdev);
3281
3282 bacpy(&hdev->static_addr, &cp->bdaddr);
3283
3284 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS, 0, NULL, 0);
3285
3286 hci_dev_unlock(hdev);
3287
3288 return err;
3289}
3290
3250static void fast_connectable_complete(struct hci_dev *hdev, u8 status) 3291static void fast_connectable_complete(struct hci_dev *hdev, u8 status)
3251{ 3292{
3252 struct pending_cmd *cmd; 3293 struct pending_cmd *cmd;
@@ -3576,6 +3617,7 @@ static const struct mgmt_handler {
3576 { set_device_id, false, MGMT_SET_DEVICE_ID_SIZE }, 3617 { set_device_id, false, MGMT_SET_DEVICE_ID_SIZE },
3577 { set_advertising, false, MGMT_SETTING_SIZE }, 3618 { set_advertising, false, MGMT_SETTING_SIZE },
3578 { set_bredr, false, MGMT_SETTING_SIZE }, 3619 { set_bredr, false, MGMT_SETTING_SIZE },
3620 { set_static_address, false, MGMT_SET_STATIC_ADDRESS_SIZE },
3579}; 3621};
3580 3622
3581 3623
@@ -3762,6 +3804,13 @@ static int powered_update_hci(struct hci_dev *hdev)
3762 hci_update_ad(&req); 3804 hci_update_ad(&req);
3763 } 3805 }
3764 3806
3807 if (lmp_le_capable(hdev)) {
3808 /* Set random address to static address if configured */
3809 if (bacmp(&hdev->static_addr, BDADDR_ANY))
3810 hci_req_add(&req, HCI_OP_LE_SET_RANDOM_ADDR, 6,
3811 &hdev->static_addr);
3812 }
3813
3765 if (test_bit(HCI_LE_PERIPHERAL, &hdev->dev_flags)) { 3814 if (test_bit(HCI_LE_PERIPHERAL, &hdev->dev_flags)) {
3766 u8 adv = 0x01; 3815 u8 adv = 0x01;
3767 3816