aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorVinicius Costa Gomes <vinicius.gomes@openbossa.org>2011-01-26 19:42:57 -0500
committerGustavo F. Padovan <padovan@profusion.mobi>2011-06-13 15:05:34 -0400
commitf1cb9af557dd8fb5d98fbcc4b5d3eb9d6d235af7 (patch)
treee2701e2cecfbf5cea1a079a7a87f8bfe020b7598 /net
parent9b3d67405b17d61ba8be9d824222fb410f487b8a (diff)
Bluetooth: Add support for resuming socket when SMP is finished
This adds support for resuming the user space traffic when SMP negotiation is complete. Signed-off-by: Vinicius Costa Gomes <vinicius.gomes@openbossa.org> Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi>
Diffstat (limited to 'net')
-rw-r--r--net/bluetooth/l2cap_core.c61
-rw-r--r--net/bluetooth/l2cap_sock.c16
-rw-r--r--net/bluetooth/smp.c40
3 files changed, 75 insertions, 42 deletions
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index 865716504396..584a4237eb3f 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -890,6 +890,23 @@ clean:
890 bh_unlock_sock(parent); 890 bh_unlock_sock(parent);
891} 891}
892 892
893static void l2cap_chan_ready(struct sock *sk)
894{
895 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
896 struct sock *parent = bt_sk(sk)->parent;
897
898 BT_DBG("sk %p, parent %p", sk, parent);
899
900 chan->conf_state = 0;
901 __clear_chan_timer(chan);
902
903 sk->sk_state = BT_CONNECTED;
904 sk->sk_state_change(sk);
905
906 if (parent)
907 parent->sk_data_ready(parent, 0);
908}
909
893static void l2cap_conn_ready(struct l2cap_conn *conn) 910static void l2cap_conn_ready(struct l2cap_conn *conn)
894{ 911{
895 struct l2cap_chan *chan; 912 struct l2cap_chan *chan;
@@ -906,13 +923,9 @@ static void l2cap_conn_ready(struct l2cap_conn *conn)
906 923
907 bh_lock_sock(sk); 924 bh_lock_sock(sk);
908 925
909 if (conn->hcon->type == LE_LINK) { 926 if (conn->hcon->type == LE_LINK)
910 __clear_chan_timer(chan);
911 l2cap_state_change(chan, BT_CONNECTED);
912 sk->sk_state_change(sk);
913 if (smp_conn_security(conn, chan->sec_level)) 927 if (smp_conn_security(conn, chan->sec_level))
914 BT_DBG("Insufficient security"); 928 l2cap_chan_ready(sk);
915 }
916 929
917 if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) { 930 if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
918 __clear_chan_timer(chan); 931 __clear_chan_timer(chan);
@@ -1675,30 +1688,6 @@ int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len)
1675 return err; 1688 return err;
1676} 1689}
1677 1690
1678static void l2cap_chan_ready(struct sock *sk)
1679{
1680 struct sock *parent = bt_sk(sk)->parent;
1681 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
1682
1683 BT_DBG("sk %p, parent %p", sk, parent);
1684
1685 chan->conf_state = 0;
1686 __clear_chan_timer(chan);
1687
1688 if (!parent) {
1689 /* Outgoing channel.
1690 * Wake up socket sleeping on connect.
1691 */
1692 l2cap_state_change(chan, BT_CONNECTED);
1693 sk->sk_state_change(sk);
1694 } else {
1695 /* Incoming channel.
1696 * Wake up socket sleeping on accept.
1697 */
1698 parent->sk_data_ready(parent, 0);
1699 }
1700}
1701
1702/* Copy frame to all raw sockets on that connection */ 1691/* Copy frame to all raw sockets on that connection */
1703static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb) 1692static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb)
1704{ 1693{
@@ -4188,6 +4177,18 @@ static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
4188 4177
4189 bh_lock_sock(sk); 4178 bh_lock_sock(sk);
4190 4179
4180 BT_DBG("chan->scid %d", chan->scid);
4181
4182 if (chan->scid == L2CAP_CID_LE_DATA) {
4183 if (!status && encrypt) {
4184 chan->sec_level = hcon->sec_level;
4185 l2cap_chan_ready(sk);
4186 }
4187
4188 bh_unlock_sock(sk);
4189 continue;
4190 }
4191
4191 if (chan->conf_state & L2CAP_CONF_CONNECT_PEND) { 4192 if (chan->conf_state & L2CAP_CONF_CONNECT_PEND) {
4192 bh_unlock_sock(sk); 4193 bh_unlock_sock(sk);
4193 continue; 4194 continue;
diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c
index 1d9c36509d7b..5c819e002fb1 100644
--- a/net/bluetooth/l2cap_sock.c
+++ b/net/bluetooth/l2cap_sock.c
@@ -29,6 +29,7 @@
29#include <net/bluetooth/bluetooth.h> 29#include <net/bluetooth/bluetooth.h>
30#include <net/bluetooth/hci_core.h> 30#include <net/bluetooth/hci_core.h>
31#include <net/bluetooth/l2cap.h> 31#include <net/bluetooth/l2cap.h>
32#include <net/bluetooth/smp.h>
32 33
33static const struct proto_ops l2cap_sock_ops; 34static const struct proto_ops l2cap_sock_ops;
34static void l2cap_sock_init(struct sock *sk, struct sock *parent); 35static void l2cap_sock_init(struct sock *sk, struct sock *parent);
@@ -562,6 +563,7 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, ch
562 struct l2cap_chan *chan = l2cap_pi(sk)->chan; 563 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
563 struct bt_security sec; 564 struct bt_security sec;
564 struct bt_power pwr; 565 struct bt_power pwr;
566 struct l2cap_conn *conn;
565 int len, err = 0; 567 int len, err = 0;
566 u32 opt; 568 u32 opt;
567 569
@@ -598,6 +600,20 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, ch
598 } 600 }
599 601
600 chan->sec_level = sec.level; 602 chan->sec_level = sec.level;
603
604 conn = chan->conn;
605 if (conn && chan->scid == L2CAP_CID_LE_DATA) {
606 if (!conn->hcon->out) {
607 err = -EINVAL;
608 break;
609 }
610
611 if (smp_conn_security(conn, sec.level))
612 break;
613
614 err = 0;
615 sk->sk_state = BT_CONFIG;
616 }
601 break; 617 break;
602 618
603 case BT_DEFER_SETUP: 619 case BT_DEFER_SETUP:
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
index 69839797b7dc..da46d76fc13d 100644
--- a/net/bluetooth/smp.c
+++ b/net/bluetooth/smp.c
@@ -336,9 +336,13 @@ static void smp_cmd_security_req(struct l2cap_conn *conn, struct sk_buff *skb)
336{ 336{
337 struct smp_cmd_security_req *rp = (void *) skb->data; 337 struct smp_cmd_security_req *rp = (void *) skb->data;
338 struct smp_cmd_pairing cp; 338 struct smp_cmd_pairing cp;
339 struct hci_conn *hcon = conn->hcon;
339 340
340 BT_DBG("conn %p", conn); 341 BT_DBG("conn %p", conn);
341 342
343 if (test_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend))
344 return;
345
342 skb_pull(skb, sizeof(*rp)); 346 skb_pull(skb, sizeof(*rp));
343 memset(&cp, 0, sizeof(cp)); 347 memset(&cp, 0, sizeof(cp));
344 348
@@ -353,6 +357,20 @@ static void smp_cmd_security_req(struct l2cap_conn *conn, struct sk_buff *skb)
353 memcpy(&conn->preq[1], &cp, sizeof(cp)); 357 memcpy(&conn->preq[1], &cp, sizeof(cp));
354 358
355 smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp); 359 smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp);
360
361 set_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend);
362}
363
364static __u8 seclevel_to_authreq(__u8 level)
365{
366 switch (level) {
367 case BT_SECURITY_HIGH:
368 /* For now we don't support bonding */
369 return SMP_AUTH_MITM;
370
371 default:
372 return SMP_AUTH_NONE;
373 }
356} 374}
357 375
358int smp_conn_security(struct l2cap_conn *conn, __u8 sec_level) 376int smp_conn_security(struct l2cap_conn *conn, __u8 sec_level)
@@ -365,21 +383,16 @@ int smp_conn_security(struct l2cap_conn *conn, __u8 sec_level)
365 if (IS_ERR(hcon->hdev->tfm)) 383 if (IS_ERR(hcon->hdev->tfm))
366 return 1; 384 return 1;
367 385
368 switch (sec_level) { 386 if (test_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend))
369 case BT_SECURITY_MEDIUM: 387 return 0;
370 /* Encrypted, no MITM protection */
371 authreq = HCI_AT_NO_BONDING_MITM;
372 break;
373 388
374 case BT_SECURITY_HIGH: 389 if (sec_level == BT_SECURITY_LOW)
375 /* Bonding, MITM protection */ 390 return 1;
376 authreq = HCI_AT_GENERAL_BONDING_MITM;
377 break;
378 391
379 case BT_SECURITY_LOW: 392 if (hcon->sec_level >= sec_level)
380 default:
381 return 1; 393 return 1;
382 } 394
395 authreq = seclevel_to_authreq(sec_level);
383 396
384 if (hcon->link_mode & HCI_LM_MASTER) { 397 if (hcon->link_mode & HCI_LM_MASTER) {
385 struct smp_cmd_pairing cp; 398 struct smp_cmd_pairing cp;
@@ -400,6 +413,9 @@ int smp_conn_security(struct l2cap_conn *conn, __u8 sec_level)
400 smp_send_cmd(conn, SMP_CMD_SECURITY_REQ, sizeof(cp), &cp); 413 smp_send_cmd(conn, SMP_CMD_SECURITY_REQ, sizeof(cp), &cp);
401 } 414 }
402 415
416 hcon->pending_sec_level = sec_level;
417 set_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend);
418
403 return 0; 419 return 0;
404} 420}
405 421