aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorSzymon Janc <szymon.janc@tieto.com>2011-03-22 08:12:22 -0400
committerGustavo F. Padovan <padovan@profusion.mobi>2011-03-31 13:22:57 -0400
commit2763eda6ccaf126633bb3180f440c8f3589f0679 (patch)
tree7239d220f4a233b31184ddb50c2914f7406c4675 /net
parentc35938b2f56547ee77b5a038fe0db394aeac59bb (diff)
Bluetooth: Add add/remove_remote_oob_data management commands
This patch adds commands to add and remove remote OOB data to the managment interface. Remote data is stored in kernel and can be used by corresponding HCI commands and events when needed. Signed-off-by: Szymon Janc <szymon.janc@tieto.com> Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi>
Diffstat (limited to 'net')
-rw-r--r--net/bluetooth/hci_core.c67
-rw-r--r--net/bluetooth/hci_event.c35
-rw-r--r--net/bluetooth/mgmt.c75
3 files changed, 177 insertions, 0 deletions
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index c20cbe5ff6db..675f0a1832ee 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -1076,6 +1076,70 @@ static void hci_cmd_timer(unsigned long arg)
1076 tasklet_schedule(&hdev->cmd_task); 1076 tasklet_schedule(&hdev->cmd_task);
1077} 1077}
1078 1078
1079struct oob_data *hci_find_remote_oob_data(struct hci_dev *hdev,
1080 bdaddr_t *bdaddr)
1081{
1082 struct oob_data *data;
1083
1084 list_for_each_entry(data, &hdev->remote_oob_data, list)
1085 if (bacmp(bdaddr, &data->bdaddr) == 0)
1086 return data;
1087
1088 return NULL;
1089}
1090
1091int hci_remove_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr)
1092{
1093 struct oob_data *data;
1094
1095 data = hci_find_remote_oob_data(hdev, bdaddr);
1096 if (!data)
1097 return -ENOENT;
1098
1099 BT_DBG("%s removing %s", hdev->name, batostr(bdaddr));
1100
1101 list_del(&data->list);
1102 kfree(data);
1103
1104 return 0;
1105}
1106
1107int hci_remote_oob_data_clear(struct hci_dev *hdev)
1108{
1109 struct oob_data *data, *n;
1110
1111 list_for_each_entry_safe(data, n, &hdev->remote_oob_data, list) {
1112 list_del(&data->list);
1113 kfree(data);
1114 }
1115
1116 return 0;
1117}
1118
1119int hci_add_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 *hash,
1120 u8 *randomizer)
1121{
1122 struct oob_data *data;
1123
1124 data = hci_find_remote_oob_data(hdev, bdaddr);
1125
1126 if (!data) {
1127 data = kmalloc(sizeof(*data), GFP_ATOMIC);
1128 if (!data)
1129 return -ENOMEM;
1130
1131 bacpy(&data->bdaddr, bdaddr);
1132 list_add(&data->list, &hdev->remote_oob_data);
1133 }
1134
1135 memcpy(data->hash, hash, sizeof(data->hash));
1136 memcpy(data->randomizer, randomizer, sizeof(data->randomizer));
1137
1138 BT_DBG("%s for %s", hdev->name, batostr(bdaddr));
1139
1140 return 0;
1141}
1142
1079/* Register HCI device */ 1143/* Register HCI device */
1080int hci_register_dev(struct hci_dev *hdev) 1144int hci_register_dev(struct hci_dev *hdev)
1081{ 1145{
@@ -1140,6 +1204,8 @@ int hci_register_dev(struct hci_dev *hdev)
1140 1204
1141 INIT_LIST_HEAD(&hdev->link_keys); 1205 INIT_LIST_HEAD(&hdev->link_keys);
1142 1206
1207 INIT_LIST_HEAD(&hdev->remote_oob_data);
1208
1143 INIT_WORK(&hdev->power_on, hci_power_on); 1209 INIT_WORK(&hdev->power_on, hci_power_on);
1144 INIT_WORK(&hdev->power_off, hci_power_off); 1210 INIT_WORK(&hdev->power_off, hci_power_off);
1145 setup_timer(&hdev->off_timer, hci_auto_off, (unsigned long) hdev); 1211 setup_timer(&hdev->off_timer, hci_auto_off, (unsigned long) hdev);
@@ -1219,6 +1285,7 @@ int hci_unregister_dev(struct hci_dev *hdev)
1219 hci_blacklist_clear(hdev); 1285 hci_blacklist_clear(hdev);
1220 hci_uuids_clear(hdev); 1286 hci_uuids_clear(hdev);
1221 hci_link_keys_clear(hdev); 1287 hci_link_keys_clear(hdev);
1288 hci_remote_oob_data_clear(hdev);
1222 hci_dev_unlock_bh(hdev); 1289 hci_dev_unlock_bh(hdev);
1223 1290
1224 __hci_dev_put(hdev); 1291 __hci_dev_put(hdev);
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 582ef60a8bc0..e0aaf3053667 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -2471,6 +2471,37 @@ static inline void hci_remote_host_features_evt(struct hci_dev *hdev, struct sk_
2471 hci_dev_unlock(hdev); 2471 hci_dev_unlock(hdev);
2472} 2472}
2473 2473
2474static inline void hci_remote_oob_data_request_evt(struct hci_dev *hdev,
2475 struct sk_buff *skb)
2476{
2477 struct hci_ev_remote_oob_data_request *ev = (void *) skb->data;
2478 struct oob_data *data;
2479
2480 BT_DBG("%s", hdev->name);
2481
2482 hci_dev_lock(hdev);
2483
2484 data = hci_find_remote_oob_data(hdev, &ev->bdaddr);
2485 if (data) {
2486 struct hci_cp_remote_oob_data_reply cp;
2487
2488 bacpy(&cp.bdaddr, &ev->bdaddr);
2489 memcpy(cp.hash, data->hash, sizeof(cp.hash));
2490 memcpy(cp.randomizer, data->randomizer, sizeof(cp.randomizer));
2491
2492 hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_REPLY, sizeof(cp),
2493 &cp);
2494 } else {
2495 struct hci_cp_remote_oob_data_neg_reply cp;
2496
2497 bacpy(&cp.bdaddr, &ev->bdaddr);
2498 hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_NEG_REPLY, sizeof(cp),
2499 &cp);
2500 }
2501
2502 hci_dev_unlock(hdev);
2503}
2504
2474static inline void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 2505static inline void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
2475{ 2506{
2476 struct hci_ev_le_conn_complete *ev = (void *) skb->data; 2507 struct hci_ev_le_conn_complete *ev = (void *) skb->data;
@@ -2673,6 +2704,10 @@ void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)
2673 hci_le_meta_evt(hdev, skb); 2704 hci_le_meta_evt(hdev, skb);
2674 break; 2705 break;
2675 2706
2707 case HCI_EV_REMOTE_OOB_DATA_REQUEST:
2708 hci_remote_oob_data_request_evt(hdev, skb);
2709 break;
2710
2676 default: 2711 default:
2677 BT_DBG("%s event 0x%x", hdev->name, event); 2712 BT_DBG("%s event 0x%x", hdev->name, event);
2678 break; 2713 break;
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 33b1f7400dab..a42dc8ca0a6f 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -1345,6 +1345,74 @@ unlock:
1345 return err; 1345 return err;
1346} 1346}
1347 1347
1348static int add_remote_oob_data(struct sock *sk, u16 index, unsigned char *data,
1349 u16 len)
1350{
1351 struct hci_dev *hdev;
1352 struct mgmt_cp_add_remote_oob_data *cp = (void *) data;
1353 int err;
1354
1355 BT_DBG("hci%u ", index);
1356
1357 if (len != sizeof(*cp))
1358 return cmd_status(sk, index, MGMT_OP_ADD_REMOTE_OOB_DATA,
1359 EINVAL);
1360
1361 hdev = hci_dev_get(index);
1362 if (!hdev)
1363 return cmd_status(sk, index, MGMT_OP_ADD_REMOTE_OOB_DATA,
1364 ENODEV);
1365
1366 hci_dev_lock_bh(hdev);
1367
1368 err = hci_add_remote_oob_data(hdev, &cp->bdaddr, cp->hash,
1369 cp->randomizer);
1370 if (err < 0)
1371 err = cmd_status(sk, index, MGMT_OP_ADD_REMOTE_OOB_DATA, -err);
1372 else
1373 err = cmd_complete(sk, index, MGMT_OP_ADD_REMOTE_OOB_DATA, NULL,
1374 0);
1375
1376 hci_dev_unlock_bh(hdev);
1377 hci_dev_put(hdev);
1378
1379 return err;
1380}
1381
1382static int remove_remote_oob_data(struct sock *sk, u16 index,
1383 unsigned char *data, u16 len)
1384{
1385 struct hci_dev *hdev;
1386 struct mgmt_cp_remove_remote_oob_data *cp = (void *) data;
1387 int err;
1388
1389 BT_DBG("hci%u ", index);
1390
1391 if (len != sizeof(*cp))
1392 return cmd_status(sk, index, MGMT_OP_REMOVE_REMOTE_OOB_DATA,
1393 EINVAL);
1394
1395 hdev = hci_dev_get(index);
1396 if (!hdev)
1397 return cmd_status(sk, index, MGMT_OP_REMOVE_REMOTE_OOB_DATA,
1398 ENODEV);
1399
1400 hci_dev_lock_bh(hdev);
1401
1402 err = hci_remove_remote_oob_data(hdev, &cp->bdaddr);
1403 if (err < 0)
1404 err = cmd_status(sk, index, MGMT_OP_REMOVE_REMOTE_OOB_DATA,
1405 -err);
1406 else
1407 err = cmd_complete(sk, index, MGMT_OP_REMOVE_REMOTE_OOB_DATA,
1408 NULL, 0);
1409
1410 hci_dev_unlock_bh(hdev);
1411 hci_dev_put(hdev);
1412
1413 return err;
1414}
1415
1348int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen) 1416int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen)
1349{ 1417{
1350 unsigned char *buf; 1418 unsigned char *buf;
@@ -1446,6 +1514,13 @@ int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen)
1446 case MGMT_OP_READ_LOCAL_OOB_DATA: 1514 case MGMT_OP_READ_LOCAL_OOB_DATA:
1447 err = read_local_oob_data(sk, index); 1515 err = read_local_oob_data(sk, index);
1448 break; 1516 break;
1517 case MGMT_OP_ADD_REMOTE_OOB_DATA:
1518 err = add_remote_oob_data(sk, index, buf + sizeof(*hdr), len);
1519 break;
1520 case MGMT_OP_REMOVE_REMOTE_OOB_DATA:
1521 err = remove_remote_oob_data(sk, index, buf + sizeof(*hdr),
1522 len);
1523 break;
1449 1524
1450 default: 1525 default:
1451 BT_DBG("Unknown op %u", opcode); 1526 BT_DBG("Unknown op %u", opcode);