aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohan Hedberg <johan.hedberg@intel.com>2012-02-16 16:56:27 -0500
committerJohan Hedberg <johan.hedberg@intel.com>2012-02-17 04:27:11 -0500
commit33ef95ed30283eb17c686a815caf1d33e966fe4a (patch)
treea989ac26b6f9c47fcf6bac5664806af2459455f6
parent7bb895d68e0c18b730bd89f2ed7e58de0e3a591a (diff)
Bluetooth: mgmt: Add support for Set Link Security command
The Set Link Security mgmt command is used to enable or disable link level security, also known as Security Mode 3. This is rarely enabled in modern systems but the command needs to be available for completeness, qualification purposes and those few systems that actually want to enable it. Signed-off-by: Johan Hedberg <johan.hedberg@intel.com> Acked-by: Marcel Holtmann <marcel@holtmann.org>
-rw-r--r--include/net/bluetooth/hci_core.h1
-rw-r--r--net/bluetooth/hci_event.c3
-rw-r--r--net/bluetooth/mgmt.c87
3 files changed, 91 insertions, 0 deletions
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index b20d990436b4..66f84adbbbef 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -994,6 +994,7 @@ int mgmt_user_passkey_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
994 u8 link_type, u8 addr_type, u8 status); 994 u8 link_type, u8 addr_type, u8 status);
995int mgmt_auth_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, 995int mgmt_auth_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
996 u8 addr_type, u8 status); 996 u8 addr_type, u8 status);
997int mgmt_auth_enable_complete(struct hci_dev *hdev, u8 status);
997int mgmt_set_local_name_complete(struct hci_dev *hdev, u8 *name, u8 status); 998int mgmt_set_local_name_complete(struct hci_dev *hdev, u8 *name, u8 status);
998int mgmt_read_local_oob_data_reply_complete(struct hci_dev *hdev, u8 *hash, 999int mgmt_read_local_oob_data_reply_complete(struct hci_dev *hdev, u8 *hash,
999 u8 *randomizer, u8 status); 1000 u8 *randomizer, u8 status);
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index b0784ee5f8b9..239e9fb8f7c5 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -254,6 +254,9 @@ static void hci_cc_write_auth_enable(struct hci_dev *hdev, struct sk_buff *skb)
254 clear_bit(HCI_AUTH, &hdev->flags); 254 clear_bit(HCI_AUTH, &hdev->flags);
255 } 255 }
256 256
257 if (test_bit(HCI_MGMT, &hdev->dev_flags))
258 mgmt_auth_enable_complete(hdev, status);
259
257 hci_req_complete(hdev, HCI_OP_WRITE_AUTH_ENABLE, status); 260 hci_req_complete(hdev, HCI_OP_WRITE_AUTH_ENABLE, status);
258} 261}
259 262
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index d5dbe402bc03..0c9fbb45d2e9 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -964,6 +964,65 @@ failed:
964 return err; 964 return err;
965} 965}
966 966
967static int set_link_security(struct sock *sk, u16 index, void *data, u16 len)
968{
969 struct mgmt_mode *cp = data;
970 struct pending_cmd *cmd;
971 struct hci_dev *hdev;
972 uint8_t val;
973 int err;
974
975 BT_DBG("request for hci%u", index);
976
977 if (len != sizeof(*cp))
978 return cmd_status(sk, index, MGMT_OP_SET_LINK_SECURITY,
979 MGMT_STATUS_INVALID_PARAMS);
980
981 hdev = hci_dev_get(index);
982 if (!hdev)
983 return cmd_status(sk, index, MGMT_OP_SET_LINK_SECURITY,
984 MGMT_STATUS_INVALID_PARAMS);
985
986 hci_dev_lock(hdev);
987
988 if (!test_bit(HCI_UP, &hdev->flags)) {
989 err = cmd_status(sk, index, MGMT_OP_SET_LINK_SECURITY,
990 MGMT_STATUS_NOT_POWERED);
991 goto failed;
992 }
993
994 if (mgmt_pending_find(MGMT_OP_SET_LINK_SECURITY, hdev)) {
995 err = cmd_status(sk, index, MGMT_OP_SET_LINK_SECURITY,
996 MGMT_STATUS_BUSY);
997 goto failed;
998 }
999
1000 val = !!cp->val;
1001
1002 if (test_bit(HCI_AUTH, &hdev->flags) == val) {
1003 err = send_settings_rsp(sk, MGMT_OP_SET_LINK_SECURITY, hdev);
1004 goto failed;
1005 }
1006
1007 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LINK_SECURITY, hdev, data, len);
1008 if (!cmd) {
1009 err = -ENOMEM;
1010 goto failed;
1011 }
1012
1013 err = hci_send_cmd(hdev, HCI_OP_WRITE_AUTH_ENABLE, sizeof(val), &val);
1014 if (err < 0) {
1015 mgmt_pending_remove(cmd);
1016 goto failed;
1017 }
1018
1019failed:
1020 hci_dev_unlock(hdev);
1021 hci_dev_put(hdev);
1022
1023 return err;
1024}
1025
967static int add_uuid(struct sock *sk, u16 index, void *data, u16 len) 1026static int add_uuid(struct sock *sk, u16 index, void *data, u16 len)
968{ 1027{
969 struct mgmt_cp_add_uuid *cp = data; 1028 struct mgmt_cp_add_uuid *cp = data;
@@ -2443,6 +2502,9 @@ int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen)
2443 case MGMT_OP_SET_PAIRABLE: 2502 case MGMT_OP_SET_PAIRABLE:
2444 err = set_pairable(sk, index, cp, len); 2503 err = set_pairable(sk, index, cp, len);
2445 break; 2504 break;
2505 case MGMT_OP_SET_LINK_SECURITY:
2506 err = set_link_security(sk, index, cp, len);
2507 break;
2446 case MGMT_OP_ADD_UUID: 2508 case MGMT_OP_ADD_UUID:
2447 err = add_uuid(sk, index, cp, len); 2509 err = add_uuid(sk, index, cp, len);
2448 break; 2510 break;
@@ -2965,6 +3027,31 @@ int mgmt_auth_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
2965 return mgmt_event(MGMT_EV_AUTH_FAILED, hdev, &ev, sizeof(ev), NULL); 3027 return mgmt_event(MGMT_EV_AUTH_FAILED, hdev, &ev, sizeof(ev), NULL);
2966} 3028}
2967 3029
3030int mgmt_auth_enable_complete(struct hci_dev *hdev, u8 status)
3031{
3032 struct cmd_lookup match = { NULL, hdev };
3033 __le32 ev;
3034 int err;
3035
3036 if (status) {
3037 u8 mgmt_err = mgmt_status(status);
3038 mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev,
3039 cmd_status_rsp, &mgmt_err);
3040 return 0;
3041 }
3042
3043 mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev, settings_rsp,
3044 &match);
3045
3046 ev = cpu_to_le32(get_current_settings(hdev));
3047 err = mgmt_event(MGMT_EV_NEW_SETTINGS, hdev, &ev, sizeof(ev), match.sk);
3048
3049 if (match.sk)
3050 sock_put(match.sk);
3051
3052 return err;
3053}
3054
2968int mgmt_set_local_name_complete(struct hci_dev *hdev, u8 *name, u8 status) 3055int mgmt_set_local_name_complete(struct hci_dev *hdev, u8 *name, u8 status)
2969{ 3056{
2970 struct pending_cmd *cmd; 3057 struct pending_cmd *cmd;