aboutsummaryrefslogtreecommitdiffstats
path: root/net/bluetooth/hci_core.c
diff options
context:
space:
mode:
authorJohan Hedberg <johan.hedberg@nokia.com>2011-01-17 07:41:05 -0500
committerGustavo F. Padovan <padovan@profusion.mobi>2011-02-07 22:40:07 -0500
commit55ed8ca10f3530de8edbbf138acb50992bf5005b (patch)
tree3145b2b995758b2cb64493fc8ec29e63d0e9f0b4 /net/bluetooth/hci_core.c
parent1aff6f09491f454d4cd9f405c783fa5e9d3168a0 (diff)
Bluetooth: Implement link key handling for the management interface
This patch adds a management commands to feed the kernel with all stored link keys as well as remove specific ones or all of them. Once the load_keys command has been called the kernel takes over link key replies. A new_key event is also added to inform userspace of newly created link keys that should be stored permanently. Signed-off-by: Johan Hedberg <johan.hedberg@nokia.com> Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi>
Diffstat (limited to 'net/bluetooth/hci_core.c')
-rw-r--r--net/bluetooth/hci_core.c85
1 files changed, 85 insertions, 0 deletions
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index 748f5a65caf4..8ca8cf147058 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -970,6 +970,88 @@ int hci_uuids_clear(struct hci_dev *hdev)
970 return 0; 970 return 0;
971} 971}
972 972
973int hci_link_keys_clear(struct hci_dev *hdev)
974{
975 struct list_head *p, *n;
976
977 list_for_each_safe(p, n, &hdev->link_keys) {
978 struct link_key *key;
979
980 key = list_entry(p, struct link_key, list);
981
982 list_del(p);
983 kfree(key);
984 }
985
986 return 0;
987}
988
989struct link_key *hci_find_link_key(struct hci_dev *hdev, bdaddr_t *bdaddr)
990{
991 struct list_head *p;
992
993 list_for_each(p, &hdev->link_keys) {
994 struct link_key *k;
995
996 k = list_entry(p, struct link_key, list);
997
998 if (bacmp(bdaddr, &k->bdaddr) == 0)
999 return k;
1000 }
1001
1002 return NULL;
1003}
1004
1005int hci_add_link_key(struct hci_dev *hdev, int new_key, bdaddr_t *bdaddr,
1006 u8 *val, u8 type, u8 pin_len)
1007{
1008 struct link_key *key, *old_key;
1009 u8 old_key_type;
1010
1011 old_key = hci_find_link_key(hdev, bdaddr);
1012 if (old_key) {
1013 old_key_type = old_key->type;
1014 key = old_key;
1015 } else {
1016 old_key_type = 0xff;
1017 key = kzalloc(sizeof(*key), GFP_ATOMIC);
1018 if (!key)
1019 return -ENOMEM;
1020 list_add(&key->list, &hdev->link_keys);
1021 }
1022
1023 BT_DBG("%s key for %s type %u", hdev->name, batostr(bdaddr), type);
1024
1025 bacpy(&key->bdaddr, bdaddr);
1026 memcpy(key->val, val, 16);
1027 key->type = type;
1028 key->pin_len = pin_len;
1029
1030 if (new_key)
1031 mgmt_new_key(hdev->id, key, old_key_type);
1032
1033 if (type == 0x06)
1034 key->type = old_key_type;
1035
1036 return 0;
1037}
1038
1039int hci_remove_link_key(struct hci_dev *hdev, bdaddr_t *bdaddr)
1040{
1041 struct link_key *key;
1042
1043 key = hci_find_link_key(hdev, bdaddr);
1044 if (!key)
1045 return -ENOENT;
1046
1047 BT_DBG("%s removing %s", hdev->name, batostr(bdaddr));
1048
1049 list_del(&key->list);
1050 kfree(key);
1051
1052 return 0;
1053}
1054
973/* Register HCI device */ 1055/* Register HCI device */
974int hci_register_dev(struct hci_dev *hdev) 1056int hci_register_dev(struct hci_dev *hdev)
975{ 1057{
@@ -1029,6 +1111,8 @@ int hci_register_dev(struct hci_dev *hdev)
1029 1111
1030 INIT_LIST_HEAD(&hdev->uuids); 1112 INIT_LIST_HEAD(&hdev->uuids);
1031 1113
1114 INIT_LIST_HEAD(&hdev->link_keys);
1115
1032 INIT_WORK(&hdev->power_on, hci_power_on); 1116 INIT_WORK(&hdev->power_on, hci_power_on);
1033 INIT_WORK(&hdev->power_off, hci_power_off); 1117 INIT_WORK(&hdev->power_off, hci_power_off);
1034 setup_timer(&hdev->off_timer, hci_auto_off, (unsigned long) hdev); 1118 setup_timer(&hdev->off_timer, hci_auto_off, (unsigned long) hdev);
@@ -1105,6 +1189,7 @@ int hci_unregister_dev(struct hci_dev *hdev)
1105 hci_dev_lock_bh(hdev); 1189 hci_dev_lock_bh(hdev);
1106 hci_blacklist_clear(hdev); 1190 hci_blacklist_clear(hdev);
1107 hci_uuids_clear(hdev); 1191 hci_uuids_clear(hdev);
1192 hci_link_keys_clear(hdev);
1108 hci_dev_unlock_bh(hdev); 1193 hci_dev_unlock_bh(hdev);
1109 1194
1110 __hci_dev_put(hdev); 1195 __hci_dev_put(hdev);