diff options
author | Marcel Holtmann <marcel@holtmann.org> | 2014-02-01 12:19:57 -0500 |
---|---|---|
committer | Johan Hedberg <johan.hedberg@intel.com> | 2014-02-13 02:51:43 -0500 |
commit | 0ab04a9c0e8e37ca495fb08c8b83615c5f144551 (patch) | |
tree | 5e2e5f8b0114d4a5b35c4dce660b8c9f08db593f /net/bluetooth/mgmt.c | |
parent | 03c515d7486b7a519728340d4b04baaad16bf806 (diff) |
Bluetooth: Add management command for Secure Connection Only Mode
With support for Secure Connections it is possible to switch the
controller into a mode that is called Secure Connections Only. In
this mode only security level 4 connections are allowed (with the
exception of security level 0 approved services).
This patch just introduces the management command and setting of the
right internal flags to enable this mode. It does not yet enforce it.
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
Diffstat (limited to 'net/bluetooth/mgmt.c')
-rw-r--r-- | net/bluetooth/mgmt.c | 41 |
1 files changed, 30 insertions, 11 deletions
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 8c94841072a8..ce7ef339b1c4 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c | |||
@@ -4043,7 +4043,7 @@ static int set_secure_conn(struct sock *sk, struct hci_dev *hdev, | |||
4043 | { | 4043 | { |
4044 | struct mgmt_mode *cp = data; | 4044 | struct mgmt_mode *cp = data; |
4045 | struct pending_cmd *cmd; | 4045 | struct pending_cmd *cmd; |
4046 | u8 status; | 4046 | u8 val, status; |
4047 | int err; | 4047 | int err; |
4048 | 4048 | ||
4049 | BT_DBG("request for %s", hdev->name); | 4049 | BT_DBG("request for %s", hdev->name); |
@@ -4058,7 +4058,7 @@ static int set_secure_conn(struct sock *sk, struct hci_dev *hdev, | |||
4058 | return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN, | 4058 | return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN, |
4059 | MGMT_STATUS_NOT_SUPPORTED); | 4059 | MGMT_STATUS_NOT_SUPPORTED); |
4060 | 4060 | ||
4061 | if (cp->val != 0x00 && cp->val != 0x01) | 4061 | if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02) |
4062 | return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN, | 4062 | return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN, |
4063 | MGMT_STATUS_INVALID_PARAMS); | 4063 | MGMT_STATUS_INVALID_PARAMS); |
4064 | 4064 | ||
@@ -4067,12 +4067,18 @@ static int set_secure_conn(struct sock *sk, struct hci_dev *hdev, | |||
4067 | if (!hdev_is_powered(hdev)) { | 4067 | if (!hdev_is_powered(hdev)) { |
4068 | bool changed; | 4068 | bool changed; |
4069 | 4069 | ||
4070 | if (cp->val) | 4070 | if (cp->val) { |
4071 | changed = !test_and_set_bit(HCI_SC_ENABLED, | 4071 | changed = !test_and_set_bit(HCI_SC_ENABLED, |
4072 | &hdev->dev_flags); | 4072 | &hdev->dev_flags); |
4073 | else | 4073 | if (cp->val == 0x02) |
4074 | set_bit(HCI_SC_ONLY, &hdev->dev_flags); | ||
4075 | else | ||
4076 | clear_bit(HCI_SC_ONLY, &hdev->dev_flags); | ||
4077 | } else { | ||
4074 | changed = test_and_clear_bit(HCI_SC_ENABLED, | 4078 | changed = test_and_clear_bit(HCI_SC_ENABLED, |
4075 | &hdev->dev_flags); | 4079 | &hdev->dev_flags); |
4080 | clear_bit(HCI_SC_ONLY, &hdev->dev_flags); | ||
4081 | } | ||
4076 | 4082 | ||
4077 | err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev); | 4083 | err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev); |
4078 | if (err < 0) | 4084 | if (err < 0) |
@@ -4090,7 +4096,10 @@ static int set_secure_conn(struct sock *sk, struct hci_dev *hdev, | |||
4090 | goto failed; | 4096 | goto failed; |
4091 | } | 4097 | } |
4092 | 4098 | ||
4093 | if (!!cp->val == test_bit(HCI_SC_ENABLED, &hdev->dev_flags)) { | 4099 | val = !!cp->val; |
4100 | |||
4101 | if (val == test_bit(HCI_SC_ENABLED, &hdev->dev_flags) && | ||
4102 | (cp->val == 0x02) == test_bit(HCI_SC_ONLY, &hdev->dev_flags)) { | ||
4094 | err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev); | 4103 | err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev); |
4095 | goto failed; | 4104 | goto failed; |
4096 | } | 4105 | } |
@@ -4101,12 +4110,17 @@ static int set_secure_conn(struct sock *sk, struct hci_dev *hdev, | |||
4101 | goto failed; | 4110 | goto failed; |
4102 | } | 4111 | } |
4103 | 4112 | ||
4104 | err = hci_send_cmd(hdev, HCI_OP_WRITE_SC_SUPPORT, 1, &cp->val); | 4113 | err = hci_send_cmd(hdev, HCI_OP_WRITE_SC_SUPPORT, 1, &val); |
4105 | if (err < 0) { | 4114 | if (err < 0) { |
4106 | mgmt_pending_remove(cmd); | 4115 | mgmt_pending_remove(cmd); |
4107 | goto failed; | 4116 | goto failed; |
4108 | } | 4117 | } |
4109 | 4118 | ||
4119 | if (cp->val == 0x02) | ||
4120 | set_bit(HCI_SC_ONLY, &hdev->dev_flags); | ||
4121 | else | ||
4122 | clear_bit(HCI_SC_ONLY, &hdev->dev_flags); | ||
4123 | |||
4110 | failed: | 4124 | failed: |
4111 | hci_dev_unlock(hdev); | 4125 | hci_dev_unlock(hdev); |
4112 | return err; | 4126 | return err; |
@@ -5063,19 +5077,24 @@ void mgmt_sc_enable_complete(struct hci_dev *hdev, u8 enable, u8 status) | |||
5063 | if (status) { | 5077 | if (status) { |
5064 | u8 mgmt_err = mgmt_status(status); | 5078 | u8 mgmt_err = mgmt_status(status); |
5065 | 5079 | ||
5066 | if (enable && test_and_clear_bit(HCI_SC_ENABLED, | 5080 | if (enable) { |
5067 | &hdev->dev_flags)) | 5081 | if (test_and_clear_bit(HCI_SC_ENABLED, |
5068 | new_settings(hdev, NULL); | 5082 | &hdev->dev_flags)) |
5083 | new_settings(hdev, NULL); | ||
5084 | clear_bit(HCI_SC_ONLY, &hdev->dev_flags); | ||
5085 | } | ||
5069 | 5086 | ||
5070 | mgmt_pending_foreach(MGMT_OP_SET_SECURE_CONN, hdev, | 5087 | mgmt_pending_foreach(MGMT_OP_SET_SECURE_CONN, hdev, |
5071 | cmd_status_rsp, &mgmt_err); | 5088 | cmd_status_rsp, &mgmt_err); |
5072 | return; | 5089 | return; |
5073 | } | 5090 | } |
5074 | 5091 | ||
5075 | if (enable) | 5092 | if (enable) { |
5076 | changed = !test_and_set_bit(HCI_SC_ENABLED, &hdev->dev_flags); | 5093 | changed = !test_and_set_bit(HCI_SC_ENABLED, &hdev->dev_flags); |
5077 | else | 5094 | } else { |
5078 | changed = test_and_clear_bit(HCI_SC_ENABLED, &hdev->dev_flags); | 5095 | changed = test_and_clear_bit(HCI_SC_ENABLED, &hdev->dev_flags); |
5096 | clear_bit(HCI_SC_ONLY, &hdev->dev_flags); | ||
5097 | } | ||
5079 | 5098 | ||
5080 | mgmt_pending_foreach(MGMT_OP_SET_SECURE_CONN, hdev, | 5099 | mgmt_pending_foreach(MGMT_OP_SET_SECURE_CONN, hdev, |
5081 | settings_rsp, &match); | 5100 | settings_rsp, &match); |