aboutsummaryrefslogtreecommitdiffstats
path: root/net/bluetooth
diff options
context:
space:
mode:
authorMarcel Holtmann <marcel@holtmann.org>2015-03-28 18:18:59 -0400
committerJohan Hedberg <johan.hedberg@intel.com>2015-03-29 00:57:02 -0400
commit57b0d3e8e7d570b693a1a253c637308130134a23 (patch)
treecd39fcfc4c0a97434e2b680bbdc09b89ee9b4a68 /net/bluetooth
parentefcd8c98e0d195c09fd9141a7af32dd83e62a5cb (diff)
Bluetooth: Fix error returns for Read Local OOB Extended Data commands
The Read Local OOB Extended Data commands are required to return the address type and the data length at least. However currently the error returns only the address type. To fix this and avoid any extra allocations or stack memory, rearrange the code so that the same path can be used for error returns. Signed-off-by: Marcel Holtmann <marcel@holtmann.org> Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
Diffstat (limited to 'net/bluetooth')
-rw-r--r--net/bluetooth/mgmt.c71
1 files changed, 34 insertions, 37 deletions
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index a9a0036ff0a7..3048092b1264 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -6414,36 +6414,30 @@ static int read_local_oob_ext_data(struct sock *sk, struct hci_dev *hdev,
6414 6414
6415 BT_DBG("%s", hdev->name); 6415 BT_DBG("%s", hdev->name);
6416 6416
6417 if (!hdev_is_powered(hdev)) 6417 if (hdev_is_powered(hdev)) {
6418 return mgmt_cmd_complete(sk, hdev->id, 6418 switch (cp->type) {
6419 MGMT_OP_READ_LOCAL_OOB_EXT_DATA, 6419 case BIT(BDADDR_BREDR):
6420 MGMT_STATUS_NOT_POWERED, 6420 status = mgmt_bredr_support(hdev);
6421 &cp->type, sizeof(cp->type)); 6421 if (status)
6422 6422 eir_len = 0;
6423 switch (cp->type) { 6423 else
6424 case BIT(BDADDR_BREDR): 6424 eir_len = 5;
6425 status = mgmt_bredr_support(hdev); 6425 break;
6426 if (status) 6426 case (BIT(BDADDR_LE_PUBLIC) | BIT(BDADDR_LE_RANDOM)):
6427 return mgmt_cmd_complete(sk, hdev->id, 6427 status = mgmt_le_support(hdev);
6428 MGMT_OP_READ_LOCAL_OOB_EXT_DATA, 6428 if (status)
6429 status, &cp->type, 6429 eir_len = 0;
6430 sizeof(cp->type)); 6430 else
6431 eir_len = 5; 6431 eir_len = 9 + 3 + 18 + 18 + 3;
6432 break; 6432 break;
6433 case (BIT(BDADDR_LE_PUBLIC) | BIT(BDADDR_LE_RANDOM)): 6433 default:
6434 status = mgmt_le_support(hdev); 6434 status = MGMT_STATUS_INVALID_PARAMS;
6435 if (status) 6435 eir_len = 0;
6436 return mgmt_cmd_complete(sk, hdev->id, 6436 break;
6437 MGMT_OP_READ_LOCAL_OOB_EXT_DATA, 6437 }
6438 status, &cp->type, 6438 } else {
6439 sizeof(cp->type)); 6439 status = MGMT_STATUS_NOT_POWERED;
6440 eir_len = 9 + 3 + 18 + 18 + 3; 6440 eir_len = 0;
6441 break;
6442 default:
6443 return mgmt_cmd_complete(sk, hdev->id,
6444 MGMT_OP_READ_LOCAL_OOB_EXT_DATA,
6445 MGMT_STATUS_INVALID_PARAMS,
6446 &cp->type, sizeof(cp->type));
6447 } 6441 }
6448 6442
6449 rp_len = sizeof(*rp) + eir_len; 6443 rp_len = sizeof(*rp) + eir_len;
@@ -6451,6 +6445,9 @@ static int read_local_oob_ext_data(struct sock *sk, struct hci_dev *hdev,
6451 if (!rp) 6445 if (!rp)
6452 return -ENOMEM; 6446 return -ENOMEM;
6453 6447
6448 if (status)
6449 goto complete;
6450
6454 hci_dev_lock(hdev); 6451 hci_dev_lock(hdev);
6455 6452
6456 eir_len = 0; 6453 eir_len = 0;
@@ -6463,11 +6460,8 @@ static int read_local_oob_ext_data(struct sock *sk, struct hci_dev *hdev,
6463 if (hci_dev_test_flag(hdev, HCI_SC_ENABLED) && 6460 if (hci_dev_test_flag(hdev, HCI_SC_ENABLED) &&
6464 smp_generate_oob(hdev, hash, rand) < 0) { 6461 smp_generate_oob(hdev, hash, rand) < 0) {
6465 hci_dev_unlock(hdev); 6462 hci_dev_unlock(hdev);
6466 err = mgmt_cmd_complete(sk, hdev->id, 6463 status = MGMT_STATUS_FAILED;
6467 MGMT_OP_READ_LOCAL_OOB_EXT_DATA, 6464 goto complete;
6468 MGMT_STATUS_FAILED,
6469 &cp->type, sizeof(cp->type));
6470 goto done;
6471 } 6465 }
6472 6466
6473 if (hci_dev_test_flag(hdev, HCI_PRIVACY)) { 6467 if (hci_dev_test_flag(hdev, HCI_PRIVACY)) {
@@ -6519,12 +6513,15 @@ static int read_local_oob_ext_data(struct sock *sk, struct hci_dev *hdev,
6519 6513
6520 hci_sock_set_flag(sk, HCI_MGMT_OOB_DATA_EVENTS); 6514 hci_sock_set_flag(sk, HCI_MGMT_OOB_DATA_EVENTS);
6521 6515
6516 status = MGMT_STATUS_SUCCESS;
6517
6518complete:
6522 rp->type = cp->type; 6519 rp->type = cp->type;
6523 rp->eir_len = cpu_to_le16(eir_len); 6520 rp->eir_len = cpu_to_le16(eir_len);
6524 6521
6525 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_EXT_DATA, 6522 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_EXT_DATA,
6526 MGMT_STATUS_SUCCESS, rp, sizeof(*rp) + eir_len); 6523 status, rp, sizeof(*rp) + eir_len);
6527 if (err < 0) 6524 if (err < 0 || status)
6528 goto done; 6525 goto done;
6529 6526
6530 err = mgmt_limited_event(MGMT_EV_LOCAL_OOB_DATA_UPDATED, hdev, 6527 err = mgmt_limited_event(MGMT_EV_LOCAL_OOB_DATA_UPDATED, hdev,