aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSzymon Janc <szymon.janc@tieto.com>2014-11-03 08:20:56 -0500
committerJohan Hedberg <johan.hedberg@intel.com>2014-11-03 08:43:05 -0500
commita736abc1ac09b824387fb75b2aa7887c6e3ed68a (patch)
tree8f2a6db8d601faec39c850882ec709d39175f653
parent845472e8d50c898c73b4f69f4edad5249b13d6a9 (diff)
Bluetooth: Fix invalid response for 'Start Discovery' command
According to Management Interface API 'Start Discovery' command should generate a Command Complete event on failure. Currently kernel is sending Command Status on early errors. This results in userspace ignoring such event due to invalid size. bluetoothd[28499]: src/adapter.c:trigger_start_discovery() bluetoothd[28499]: src/adapter.c:cancel_passive_scanning() bluetoothd[28499]: src/adapter.c:start_discovery_timeout() bluetoothd[28499]: src/adapter.c:start_discovery_complete() status 0x0a bluetoothd[28499]: Wrong size of start discovery return parameters Reported-by: Jukka Taimisto <jtt@codenomicon.com> Signed-off-by: Szymon Janc <szymon.janc@tieto.com> Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
-rw-r--r--net/bluetooth/mgmt.c56
1 files changed, 35 insertions, 21 deletions
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 9c4daf715cf8..ce0272c6f71f 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -3727,20 +3727,23 @@ static int start_discovery(struct sock *sk, struct hci_dev *hdev,
3727 hci_dev_lock(hdev); 3727 hci_dev_lock(hdev);
3728 3728
3729 if (!hdev_is_powered(hdev)) { 3729 if (!hdev_is_powered(hdev)) {
3730 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY, 3730 err = cmd_complete(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3731 MGMT_STATUS_NOT_POWERED); 3731 MGMT_STATUS_NOT_POWERED,
3732 &cp->type, sizeof(cp->type));
3732 goto failed; 3733 goto failed;
3733 } 3734 }
3734 3735
3735 if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags)) { 3736 if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags)) {
3736 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY, 3737 err = cmd_complete(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3737 MGMT_STATUS_BUSY); 3738 MGMT_STATUS_BUSY, &cp->type,
3739 sizeof(cp->type));
3738 goto failed; 3740 goto failed;
3739 } 3741 }
3740 3742
3741 if (hdev->discovery.state != DISCOVERY_STOPPED) { 3743 if (hdev->discovery.state != DISCOVERY_STOPPED) {
3742 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY, 3744 err = cmd_complete(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3743 MGMT_STATUS_BUSY); 3745 MGMT_STATUS_BUSY, &cp->type,
3746 sizeof(cp->type));
3744 goto failed; 3747 goto failed;
3745 } 3748 }
3746 3749
@@ -3758,15 +3761,18 @@ static int start_discovery(struct sock *sk, struct hci_dev *hdev,
3758 case DISCOV_TYPE_BREDR: 3761 case DISCOV_TYPE_BREDR:
3759 status = mgmt_bredr_support(hdev); 3762 status = mgmt_bredr_support(hdev);
3760 if (status) { 3763 if (status) {
3761 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY, 3764 err = cmd_complete(sk, hdev->id,
3762 status); 3765 MGMT_OP_START_DISCOVERY, status,
3766 &cp->type, sizeof(cp->type));
3763 mgmt_pending_remove(cmd); 3767 mgmt_pending_remove(cmd);
3764 goto failed; 3768 goto failed;
3765 } 3769 }
3766 3770
3767 if (test_bit(HCI_INQUIRY, &hdev->flags)) { 3771 if (test_bit(HCI_INQUIRY, &hdev->flags)) {
3768 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY, 3772 err = cmd_complete(sk, hdev->id,
3769 MGMT_STATUS_BUSY); 3773 MGMT_OP_START_DISCOVERY,
3774 MGMT_STATUS_BUSY, &cp->type,
3775 sizeof(cp->type));
3770 mgmt_pending_remove(cmd); 3776 mgmt_pending_remove(cmd);
3771 goto failed; 3777 goto failed;
3772 } 3778 }
@@ -3783,16 +3789,19 @@ static int start_discovery(struct sock *sk, struct hci_dev *hdev,
3783 case DISCOV_TYPE_INTERLEAVED: 3789 case DISCOV_TYPE_INTERLEAVED:
3784 status = mgmt_le_support(hdev); 3790 status = mgmt_le_support(hdev);
3785 if (status) { 3791 if (status) {
3786 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY, 3792 err = cmd_complete(sk, hdev->id,
3787 status); 3793 MGMT_OP_START_DISCOVERY, status,
3794 &cp->type, sizeof(cp->type));
3788 mgmt_pending_remove(cmd); 3795 mgmt_pending_remove(cmd);
3789 goto failed; 3796 goto failed;
3790 } 3797 }
3791 3798
3792 if (hdev->discovery.type == DISCOV_TYPE_INTERLEAVED && 3799 if (hdev->discovery.type == DISCOV_TYPE_INTERLEAVED &&
3793 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) { 3800 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
3794 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY, 3801 err = cmd_complete(sk, hdev->id,
3795 MGMT_STATUS_NOT_SUPPORTED); 3802 MGMT_OP_START_DISCOVERY,
3803 MGMT_STATUS_NOT_SUPPORTED,
3804 &cp->type, sizeof(cp->type));
3796 mgmt_pending_remove(cmd); 3805 mgmt_pending_remove(cmd);
3797 goto failed; 3806 goto failed;
3798 } 3807 }
@@ -3804,9 +3813,11 @@ static int start_discovery(struct sock *sk, struct hci_dev *hdev,
3804 */ 3813 */
3805 if (hci_conn_hash_lookup_state(hdev, LE_LINK, 3814 if (hci_conn_hash_lookup_state(hdev, LE_LINK,
3806 BT_CONNECT)) { 3815 BT_CONNECT)) {
3807 err = cmd_status(sk, hdev->id, 3816 err = cmd_complete(sk, hdev->id,
3808 MGMT_OP_START_DISCOVERY, 3817 MGMT_OP_START_DISCOVERY,
3809 MGMT_STATUS_REJECTED); 3818 MGMT_STATUS_REJECTED,
3819 &cp->type,
3820 sizeof(cp->type));
3810 mgmt_pending_remove(cmd); 3821 mgmt_pending_remove(cmd);
3811 goto failed; 3822 goto failed;
3812 } 3823 }
@@ -3829,8 +3840,10 @@ static int start_discovery(struct sock *sk, struct hci_dev *hdev,
3829 */ 3840 */
3830 err = hci_update_random_address(&req, true, &own_addr_type); 3841 err = hci_update_random_address(&req, true, &own_addr_type);
3831 if (err < 0) { 3842 if (err < 0) {
3832 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY, 3843 err = cmd_complete(sk, hdev->id,
3833 MGMT_STATUS_FAILED); 3844 MGMT_OP_START_DISCOVERY,
3845 MGMT_STATUS_FAILED,
3846 &cp->type, sizeof(cp->type));
3834 mgmt_pending_remove(cmd); 3847 mgmt_pending_remove(cmd);
3835 goto failed; 3848 goto failed;
3836 } 3849 }
@@ -3850,8 +3863,9 @@ static int start_discovery(struct sock *sk, struct hci_dev *hdev,
3850 break; 3863 break;
3851 3864
3852 default: 3865 default:
3853 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY, 3866 err = cmd_complete(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3854 MGMT_STATUS_INVALID_PARAMS); 3867 MGMT_STATUS_INVALID_PARAMS,
3868 &cp->type, sizeof(cp->type));
3855 mgmt_pending_remove(cmd); 3869 mgmt_pending_remove(cmd);
3856 goto failed; 3870 goto failed;
3857 } 3871 }