aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorJohan Hedberg <johan.hedberg@intel.com>2014-08-13 08:12:32 -0400
committerMarcel Holtmann <marcel@holtmann.org>2014-12-03 10:51:20 -0500
commitef8efe4bf8b5fe1a9342ae964c428aed1be7863b (patch)
treefa5ed6ec8be7f501c12d9ca6376bbfdb8a248146 /net
parent858cdc78be8be19b7176cafe06d3db3acfb345d4 (diff)
Bluetooth: Add skeleton for BR/EDR SMP channel
This patch adds the very basic code for creating and destroying SMP L2CAP channels for BR/EDR connections. Signed-off-by: Johan Hedberg <johan.hedberg@intel.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
Diffstat (limited to 'net')
-rw-r--r--net/bluetooth/smp.c89
1 files changed, 71 insertions, 18 deletions
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
index 779160485a50..135e725119c5 100644
--- a/net/bluetooth/smp.c
+++ b/net/bluetooth/smp.c
@@ -2504,6 +2504,9 @@ static void smp_resume_cb(struct l2cap_chan *chan)
2504 2504
2505 BT_DBG("chan %p", chan); 2505 BT_DBG("chan %p", chan);
2506 2506
2507 if (hcon->type == ACL_LINK)
2508 return;
2509
2507 if (!smp) 2510 if (!smp)
2508 return; 2511 return;
2509 2512
@@ -2527,10 +2530,14 @@ static void smp_ready_cb(struct l2cap_chan *chan)
2527 2530
2528static int smp_recv_cb(struct l2cap_chan *chan, struct sk_buff *skb) 2531static int smp_recv_cb(struct l2cap_chan *chan, struct sk_buff *skb)
2529{ 2532{
2533 struct hci_conn *hcon = chan->conn->hcon;
2530 int err; 2534 int err;
2531 2535
2532 BT_DBG("chan %p", chan); 2536 BT_DBG("chan %p", chan);
2533 2537
2538 if (hcon->type == ACL_LINK)
2539 return -EOPNOTSUPP;
2540
2534 err = smp_sig_channel(chan, skb); 2541 err = smp_sig_channel(chan, skb);
2535 if (err) { 2542 if (err) {
2536 struct smp_chan *smp = chan->data; 2543 struct smp_chan *smp = chan->data;
@@ -2627,34 +2634,40 @@ static const struct l2cap_ops smp_root_chan_ops = {
2627 .memcpy_fromiovec = l2cap_chan_no_memcpy_fromiovec, 2634 .memcpy_fromiovec = l2cap_chan_no_memcpy_fromiovec,
2628}; 2635};
2629 2636
2630int smp_register(struct hci_dev *hdev) 2637static struct l2cap_chan *smp_add_cid(struct hci_dev *hdev, u16 cid)
2631{ 2638{
2632 struct l2cap_chan *chan; 2639 struct l2cap_chan *chan;
2633 struct crypto_blkcipher *tfm_aes; 2640 struct crypto_blkcipher *tfm_aes;
2634 2641
2635 BT_DBG("%s", hdev->name); 2642 if (cid == L2CAP_CID_SMP_BREDR) {
2643 tfm_aes = NULL;
2644 goto create_chan;
2645 }
2636 2646
2637 tfm_aes = crypto_alloc_blkcipher("ecb(aes)", 0, 0); 2647 tfm_aes = crypto_alloc_blkcipher("ecb(aes)", 0, 0);
2638 if (IS_ERR(tfm_aes)) { 2648 if (IS_ERR(tfm_aes)) {
2639 int err = PTR_ERR(tfm_aes);
2640 BT_ERR("Unable to create crypto context"); 2649 BT_ERR("Unable to create crypto context");
2641 return err; 2650 return ERR_PTR(PTR_ERR(tfm_aes));
2642 } 2651 }
2643 2652
2653create_chan:
2644 chan = l2cap_chan_create(); 2654 chan = l2cap_chan_create();
2645 if (!chan) { 2655 if (!chan) {
2646 crypto_free_blkcipher(tfm_aes); 2656 crypto_free_blkcipher(tfm_aes);
2647 return -ENOMEM; 2657 return ERR_PTR(-ENOMEM);
2648 } 2658 }
2649 2659
2650 chan->data = tfm_aes; 2660 chan->data = tfm_aes;
2651 2661
2652 l2cap_add_scid(chan, L2CAP_CID_SMP); 2662 l2cap_add_scid(chan, cid);
2653 2663
2654 l2cap_chan_set_defaults(chan); 2664 l2cap_chan_set_defaults(chan);
2655 2665
2656 bacpy(&chan->src, &hdev->bdaddr); 2666 bacpy(&chan->src, &hdev->bdaddr);
2657 chan->src_type = BDADDR_LE_PUBLIC; 2667 if (cid == L2CAP_CID_SMP)
2668 chan->src_type = BDADDR_LE_PUBLIC;
2669 else
2670 chan->src_type = BDADDR_BREDR;
2658 chan->state = BT_LISTEN; 2671 chan->state = BT_LISTEN;
2659 chan->mode = L2CAP_MODE_BASIC; 2672 chan->mode = L2CAP_MODE_BASIC;
2660 chan->imtu = L2CAP_DEFAULT_MTU; 2673 chan->imtu = L2CAP_DEFAULT_MTU;
@@ -2663,20 +2676,14 @@ int smp_register(struct hci_dev *hdev)
2663 /* Set correct nesting level for a parent/listening channel */ 2676 /* Set correct nesting level for a parent/listening channel */
2664 atomic_set(&chan->nesting, L2CAP_NESTING_PARENT); 2677 atomic_set(&chan->nesting, L2CAP_NESTING_PARENT);
2665 2678
2666 hdev->smp_data = chan; 2679 return chan;
2667
2668 return 0;
2669} 2680}
2670 2681
2671void smp_unregister(struct hci_dev *hdev) 2682static void smp_del_chan(struct l2cap_chan *chan)
2672{ 2683{
2673 struct l2cap_chan *chan = hdev->smp_data; 2684 struct crypto_blkcipher *tfm_aes;
2674 struct crypto_blkcipher *tfm_aes;
2675
2676 if (!chan)
2677 return;
2678 2685
2679 BT_DBG("%s chan %p", hdev->name, chan); 2686 BT_DBG("chan %p", chan);
2680 2687
2681 tfm_aes = chan->data; 2688 tfm_aes = chan->data;
2682 if (tfm_aes) { 2689 if (tfm_aes) {
@@ -2684,6 +2691,52 @@ void smp_unregister(struct hci_dev *hdev)
2684 crypto_free_blkcipher(tfm_aes); 2691 crypto_free_blkcipher(tfm_aes);
2685 } 2692 }
2686 2693
2687 hdev->smp_data = NULL;
2688 l2cap_chan_put(chan); 2694 l2cap_chan_put(chan);
2689} 2695}
2696
2697int smp_register(struct hci_dev *hdev)
2698{
2699 struct l2cap_chan *chan;
2700
2701 BT_DBG("%s", hdev->name);
2702
2703 chan = smp_add_cid(hdev, L2CAP_CID_SMP);
2704 if (IS_ERR(chan))
2705 return PTR_ERR(chan);
2706
2707 hdev->smp_data = chan;
2708
2709 if (!lmp_sc_capable(hdev) &&
2710 !test_bit(HCI_FORCE_LESC, &hdev->dbg_flags))
2711 return 0;
2712
2713 chan = smp_add_cid(hdev, L2CAP_CID_SMP_BREDR);
2714 if (IS_ERR(chan)) {
2715 int err = PTR_ERR(chan);
2716 chan = hdev->smp_data;
2717 hdev->smp_data = NULL;
2718 smp_del_chan(chan);
2719 return err;
2720 }
2721
2722 hdev->smp_bredr_data = chan;
2723
2724 return 0;
2725}
2726
2727void smp_unregister(struct hci_dev *hdev)
2728{
2729 struct l2cap_chan *chan;
2730
2731 if (hdev->smp_bredr_data) {
2732 chan = hdev->smp_bredr_data;
2733 hdev->smp_bredr_data = NULL;
2734 smp_del_chan(chan);
2735 }
2736
2737 if (hdev->smp_data) {
2738 chan = hdev->smp_data;
2739 hdev->smp_data = NULL;
2740 smp_del_chan(chan);
2741 }
2742}