summaryrefslogtreecommitdiffstats
path: root/net/bluetooth/smp.c
diff options
context:
space:
mode:
authorJohan Hedberg <johan.hedberg@intel.com>2014-08-08 02:37:16 -0400
committerMarcel Holtmann <marcel@holtmann.org>2014-08-14 02:49:18 -0400
commit70db83c4bcdc1447bbcb318389561c90d7056b18 (patch)
treec175a11638d84a71b3349015b0c8b9c8ce14d61e /net/bluetooth/smp.c
parentf193844c51e88ea3d2137bb0c1d38d27d37691a2 (diff)
Bluetooth: Add SMP L2CAP channel skeleton
This patch creates the initial SMP L2CAP channels and a skeleton for their callbacks. There is one per-adapter channel created upon adapter registration, and then one channel per-connection created through the new_connection callback. The channels are registered with the reserved CID 0x1f for now in order to not conflict with existing SMP functionality. Once everything is in place the value can be changed to what it should be, i.e. L2CAP_CID_SMP. Signed-off-by: Johan Hedberg <johan.hedberg@intel.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
Diffstat (limited to 'net/bluetooth/smp.c')
-rw-r--r--net/bluetooth/smp.c131
1 files changed, 130 insertions, 1 deletions
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
index ab07649ecc77..2362ae35a4d5 100644
--- a/net/bluetooth/smp.c
+++ b/net/bluetooth/smp.c
@@ -1456,8 +1456,106 @@ int smp_distribute_keys(struct l2cap_conn *conn)
1456 return 0; 1456 return 0;
1457} 1457}
1458 1458
1459static void smp_teardown_cb(struct l2cap_chan *chan, int err)
1460{
1461 struct l2cap_conn *conn = chan->conn;
1462
1463 BT_DBG("chan %p", chan);
1464
1465 conn->smp = NULL;
1466 l2cap_chan_put(chan);
1467}
1468
1469static void smp_ready_cb(struct l2cap_chan *chan)
1470{
1471 struct l2cap_conn *conn = chan->conn;
1472
1473 BT_DBG("chan %p", chan);
1474
1475 conn->smp = chan;
1476 l2cap_chan_hold(chan);
1477}
1478
1479static struct sk_buff *smp_alloc_skb_cb(struct l2cap_chan *chan,
1480 unsigned long hdr_len,
1481 unsigned long len, int nb)
1482{
1483 struct sk_buff *skb;
1484
1485 skb = bt_skb_alloc(hdr_len + len, GFP_KERNEL);
1486 if (!skb)
1487 return ERR_PTR(-ENOMEM);
1488
1489 skb->priority = HCI_PRIO_MAX;
1490 bt_cb(skb)->chan = chan;
1491
1492 return skb;
1493}
1494
1495static const struct l2cap_ops smp_chan_ops = {
1496 .name = "Security Manager",
1497 .ready = smp_ready_cb,
1498 .alloc_skb = smp_alloc_skb_cb,
1499 .teardown = smp_teardown_cb,
1500
1501 .new_connection = l2cap_chan_no_new_connection,
1502 .recv = l2cap_chan_no_recv,
1503 .state_change = l2cap_chan_no_state_change,
1504 .close = l2cap_chan_no_close,
1505 .defer = l2cap_chan_no_defer,
1506 .suspend = l2cap_chan_no_suspend,
1507 .resume = l2cap_chan_no_resume,
1508 .set_shutdown = l2cap_chan_no_set_shutdown,
1509 .get_sndtimeo = l2cap_chan_no_get_sndtimeo,
1510 .memcpy_fromiovec = l2cap_chan_no_memcpy_fromiovec,
1511};
1512
1513static inline struct l2cap_chan *smp_new_conn_cb(struct l2cap_chan *pchan)
1514{
1515 struct l2cap_chan *chan;
1516
1517 BT_DBG("pchan %p", pchan);
1518
1519 chan = l2cap_chan_create();
1520 if (!chan)
1521 return NULL;
1522
1523 chan->chan_type = pchan->chan_type;
1524 chan->ops = &smp_chan_ops;
1525 chan->scid = pchan->scid;
1526 chan->dcid = chan->scid;
1527 chan->imtu = pchan->imtu;
1528 chan->omtu = pchan->omtu;
1529 chan->mode = pchan->mode;
1530
1531 BT_DBG("created chan %p", chan);
1532
1533 return chan;
1534}
1535
1536static const struct l2cap_ops smp_root_chan_ops = {
1537 .name = "Security Manager Root",
1538 .new_connection = smp_new_conn_cb,
1539
1540 /* None of these are implemented for the root channel */
1541 .close = l2cap_chan_no_close,
1542 .alloc_skb = l2cap_chan_no_alloc_skb,
1543 .recv = l2cap_chan_no_recv,
1544 .state_change = l2cap_chan_no_state_change,
1545 .teardown = l2cap_chan_no_teardown,
1546 .ready = l2cap_chan_no_ready,
1547 .defer = l2cap_chan_no_defer,
1548 .suspend = l2cap_chan_no_suspend,
1549 .resume = l2cap_chan_no_resume,
1550 .set_shutdown = l2cap_chan_no_set_shutdown,
1551 .get_sndtimeo = l2cap_chan_no_get_sndtimeo,
1552 .memcpy_fromiovec = l2cap_chan_no_memcpy_fromiovec,
1553};
1554
1459int smp_register(struct hci_dev *hdev) 1555int smp_register(struct hci_dev *hdev)
1460{ 1556{
1557 struct l2cap_chan *chan;
1558
1461 BT_DBG("%s", hdev->name); 1559 BT_DBG("%s", hdev->name);
1462 1560
1463 hdev->tfm_aes = crypto_alloc_blkcipher("ecb(aes)", 0, 1561 hdev->tfm_aes = crypto_alloc_blkcipher("ecb(aes)", 0,
@@ -1469,15 +1567,46 @@ int smp_register(struct hci_dev *hdev)
1469 return err; 1567 return err;
1470 } 1568 }
1471 1569
1570 chan = l2cap_chan_create();
1571 if (!chan) {
1572 crypto_free_blkcipher(hdev->tfm_aes);
1573 hdev->tfm_aes = NULL;
1574 return -ENOMEM;
1575 }
1576
1577 /* FIXME: Using reserved 0x1f value for now - to be changed to
1578 * L2CAP_CID_SMP once all functionality is in place.
1579 */
1580 l2cap_add_scid(chan, 0x1f);
1581
1582 l2cap_chan_set_defaults(chan);
1583
1584 bacpy(&chan->src, &hdev->bdaddr);
1585 chan->src_type = BDADDR_LE_PUBLIC;
1586 chan->state = BT_LISTEN;
1587 chan->mode = L2CAP_MODE_BASIC;
1588 chan->imtu = L2CAP_DEFAULT_MTU;
1589 chan->ops = &smp_root_chan_ops;
1590
1591 hdev->smp_data = chan;
1592
1472 return 0; 1593 return 0;
1473} 1594}
1474 1595
1475void smp_unregister(struct hci_dev *hdev) 1596void smp_unregister(struct hci_dev *hdev)
1476{ 1597{
1477 BT_DBG("%s", hdev->name); 1598 struct l2cap_chan *chan = hdev->smp_data;
1599
1600 if (!chan)
1601 return;
1602
1603 BT_DBG("%s chan %p", hdev->name, chan);
1478 1604
1479 if (hdev->tfm_aes) { 1605 if (hdev->tfm_aes) {
1480 crypto_free_blkcipher(hdev->tfm_aes); 1606 crypto_free_blkcipher(hdev->tfm_aes);
1481 hdev->tfm_aes = NULL; 1607 hdev->tfm_aes = NULL;
1482 } 1608 }
1609
1610 hdev->smp_data = NULL;
1611 l2cap_chan_put(chan);
1483} 1612}