aboutsummaryrefslogtreecommitdiffstats
path: root/net/bluetooth/mgmt.c
diff options
context:
space:
mode:
authorMarcel Holtmann <marcel@holtmann.org>2014-02-01 12:19:57 -0500
committerJohan Hedberg <johan.hedberg@intel.com>2014-02-13 02:51:43 -0500
commit0ab04a9c0e8e37ca495fb08c8b83615c5f144551 (patch)
tree5e2e5f8b0114d4a5b35c4dce660b8c9f08db593f /net/bluetooth/mgmt.c
parent03c515d7486b7a519728340d4b04baaad16bf806 (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.c41
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
4110failed: 4124failed:
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);