aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFrédéric Dalleau <frederic.dalleau@linux.intel.com>2012-11-21 04:51:12 -0500
committerGustavo Padovan <gustavo.padovan@collabora.co.uk>2012-12-03 12:59:58 -0500
commit20714bfef84d3e690c9c6f8e9cd46543b5ae1eed (patch)
treeaa1ac5c6a0b959382ed2c6a2be52b45414d4cf08
parentb96e9c671b05f95126753a22145d4509d45ca197 (diff)
Bluetooth: Implement deferred sco socket setup
In order to authenticate and configure an incoming SCO connection, the BT_DEFER_SETUP option was added. This option is intended to defer reply to Connect Request on SCO sockets. When a connection is requested, the listening socket is unblocked but the effective connection setup happens only on first recv. Any send between accept and recv fails with -ENOTCONN. Signed-off-by: Frédéric Dalleau <frederic.dalleau@linux.intel.com> Signed-off-by: Gustavo Padovan <gustavo.padovan@collabora.co.uk>
-rw-r--r--include/net/bluetooth/hci_core.h9
-rw-r--r--net/bluetooth/hci_event.c52
-rw-r--r--net/bluetooth/sco.c35
3 files changed, 86 insertions, 10 deletions
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index ef5b85dac3f7..76891a914e75 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -376,7 +376,7 @@ extern int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt);
376extern int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, 376extern int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb,
377 u16 flags); 377 u16 flags);
378 378
379extern int sco_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr); 379extern int sco_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, __u8 *flags);
380extern void sco_connect_cfm(struct hci_conn *hcon, __u8 status); 380extern void sco_connect_cfm(struct hci_conn *hcon, __u8 status);
381extern void sco_disconn_cfm(struct hci_conn *hcon, __u8 reason); 381extern void sco_disconn_cfm(struct hci_conn *hcon, __u8 reason);
382extern int sco_recv_scodata(struct hci_conn *hcon, struct sk_buff *skb); 382extern int sco_recv_scodata(struct hci_conn *hcon, struct sk_buff *skb);
@@ -577,6 +577,7 @@ struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst);
577int hci_conn_del(struct hci_conn *conn); 577int hci_conn_del(struct hci_conn *conn);
578void hci_conn_hash_flush(struct hci_dev *hdev); 578void hci_conn_hash_flush(struct hci_dev *hdev);
579void hci_conn_check_pending(struct hci_dev *hdev); 579void hci_conn_check_pending(struct hci_dev *hdev);
580void hci_conn_accept(struct hci_conn *conn, int mask);
580 581
581struct hci_chan *hci_chan_create(struct hci_conn *conn); 582struct hci_chan *hci_chan_create(struct hci_conn *conn);
582void hci_chan_del(struct hci_chan *chan); 583void hci_chan_del(struct hci_chan *chan);
@@ -779,8 +780,10 @@ void hci_conn_del_sysfs(struct hci_conn *conn);
779#define lmp_host_le_br_capable(dev) ((dev)->host_features[0] & LMP_HOST_LE_BREDR) 780#define lmp_host_le_br_capable(dev) ((dev)->host_features[0] & LMP_HOST_LE_BREDR)
780 781
781/* ----- HCI protocols ----- */ 782/* ----- HCI protocols ----- */
783#define HCI_PROTO_DEFER 0x01
784
782static inline int hci_proto_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, 785static inline int hci_proto_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr,
783 __u8 type) 786 __u8 type, __u8 *flags)
784{ 787{
785 switch (type) { 788 switch (type) {
786 case ACL_LINK: 789 case ACL_LINK:
@@ -788,7 +791,7 @@ static inline int hci_proto_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr,
788 791
789 case SCO_LINK: 792 case SCO_LINK:
790 case ESCO_LINK: 793 case ESCO_LINK:
791 return sco_connect_ind(hdev, bdaddr); 794 return sco_connect_ind(hdev, bdaddr, flags);
792 795
793 default: 796 default:
794 BT_ERR("unknown link type %d", type); 797 BT_ERR("unknown link type %d", type);
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 9f5c5f244502..3843f1897c86 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -2047,15 +2047,53 @@ unlock:
2047 hci_conn_check_pending(hdev); 2047 hci_conn_check_pending(hdev);
2048} 2048}
2049 2049
2050void hci_conn_accept(struct hci_conn *conn, int mask)
2051{
2052 struct hci_dev *hdev = conn->hdev;
2053
2054 BT_DBG("conn %p", conn);
2055
2056 conn->state = BT_CONFIG;
2057
2058 if (!lmp_esco_capable(hdev)) {
2059 struct hci_cp_accept_conn_req cp;
2060
2061 bacpy(&cp.bdaddr, &conn->dst);
2062
2063 if (lmp_rswitch_capable(hdev) && (mask & HCI_LM_MASTER))
2064 cp.role = 0x00; /* Become master */
2065 else
2066 cp.role = 0x01; /* Remain slave */
2067
2068 hci_send_cmd(hdev, HCI_OP_ACCEPT_CONN_REQ, sizeof(cp), &cp);
2069 } else /* lmp_esco_capable(hdev)) */ {
2070 struct hci_cp_accept_sync_conn_req cp;
2071
2072 bacpy(&cp.bdaddr, &conn->dst);
2073 cp.pkt_type = cpu_to_le16(conn->pkt_type);
2074
2075 cp.tx_bandwidth = __constant_cpu_to_le32(0x00001f40);
2076 cp.rx_bandwidth = __constant_cpu_to_le32(0x00001f40);
2077 cp.max_latency = __constant_cpu_to_le16(0xffff);
2078 cp.content_format = cpu_to_le16(hdev->voice_setting);
2079 cp.retrans_effort = 0xff;
2080
2081 hci_send_cmd(hdev, HCI_OP_ACCEPT_SYNC_CONN_REQ,
2082 sizeof(cp), &cp);
2083 }
2084}
2085
2050static void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb) 2086static void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
2051{ 2087{
2052 struct hci_ev_conn_request *ev = (void *) skb->data; 2088 struct hci_ev_conn_request *ev = (void *) skb->data;
2053 int mask = hdev->link_mode; 2089 int mask = hdev->link_mode;
2090 __u8 flags = 0;
2054 2091
2055 BT_DBG("%s bdaddr %pMR type 0x%x", hdev->name, &ev->bdaddr, 2092 BT_DBG("%s bdaddr %pMR type 0x%x", hdev->name, &ev->bdaddr,
2056 ev->link_type); 2093 ev->link_type);
2057 2094
2058 mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, ev->link_type); 2095 mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, ev->link_type,
2096 &flags);
2059 2097
2060 if ((mask & HCI_LM_ACCEPT) && 2098 if ((mask & HCI_LM_ACCEPT) &&
2061 !hci_blacklist_lookup(hdev, &ev->bdaddr)) { 2099 !hci_blacklist_lookup(hdev, &ev->bdaddr)) {
@@ -2081,12 +2119,13 @@ static void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
2081 } 2119 }
2082 2120
2083 memcpy(conn->dev_class, ev->dev_class, 3); 2121 memcpy(conn->dev_class, ev->dev_class, 3);
2084 conn->state = BT_CONNECT;
2085 2122
2086 hci_dev_unlock(hdev); 2123 hci_dev_unlock(hdev);
2087 2124
2088 if (ev->link_type == ACL_LINK || !lmp_esco_capable(hdev)) { 2125 if (ev->link_type == ACL_LINK ||
2126 (!(flags & HCI_PROTO_DEFER) && !lmp_esco_capable(hdev))) {
2089 struct hci_cp_accept_conn_req cp; 2127 struct hci_cp_accept_conn_req cp;
2128 conn->state = BT_CONNECT;
2090 2129
2091 bacpy(&cp.bdaddr, &ev->bdaddr); 2130 bacpy(&cp.bdaddr, &ev->bdaddr);
2092 2131
@@ -2097,8 +2136,9 @@ static void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
2097 2136
2098 hci_send_cmd(hdev, HCI_OP_ACCEPT_CONN_REQ, sizeof(cp), 2137 hci_send_cmd(hdev, HCI_OP_ACCEPT_CONN_REQ, sizeof(cp),
2099 &cp); 2138 &cp);
2100 } else { 2139 } else if (!(flags & HCI_PROTO_DEFER)) {
2101 struct hci_cp_accept_sync_conn_req cp; 2140 struct hci_cp_accept_sync_conn_req cp;
2141 conn->state = BT_CONNECT;
2102 2142
2103 bacpy(&cp.bdaddr, &ev->bdaddr); 2143 bacpy(&cp.bdaddr, &ev->bdaddr);
2104 cp.pkt_type = cpu_to_le16(conn->pkt_type); 2144 cp.pkt_type = cpu_to_le16(conn->pkt_type);
@@ -2111,6 +2151,10 @@ static void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
2111 2151
2112 hci_send_cmd(hdev, HCI_OP_ACCEPT_SYNC_CONN_REQ, 2152 hci_send_cmd(hdev, HCI_OP_ACCEPT_SYNC_CONN_REQ,
2113 sizeof(cp), &cp); 2153 sizeof(cp), &cp);
2154 } else {
2155 conn->state = BT_CONNECT2;
2156 hci_proto_connect_cfm(conn, 0);
2157 hci_conn_put(conn);
2114 } 2158 }
2115 } else { 2159 } else {
2116 /* Connection rejected */ 2160 /* Connection rejected */
diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c
index c6678f2bffc9..eea17cdcaf7f 100644
--- a/net/bluetooth/sco.c
+++ b/net/bluetooth/sco.c
@@ -397,6 +397,7 @@ static void sco_sock_init(struct sock *sk, struct sock *parent)
397 397
398 if (parent) { 398 if (parent) {
399 sk->sk_type = parent->sk_type; 399 sk->sk_type = parent->sk_type;
400 bt_sk(sk)->flags = bt_sk(parent)->flags;
400 security_sk_clone(parent, sk); 401 security_sk_clone(parent, sk);
401 } 402 }
402} 403}
@@ -662,6 +663,28 @@ static int sco_sock_sendmsg(struct kiocb *iocb, struct socket *sock,
662 return err; 663 return err;
663} 664}
664 665
666static int sco_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
667 struct msghdr *msg, size_t len, int flags)
668{
669 struct sock *sk = sock->sk;
670 struct sco_pinfo *pi = sco_pi(sk);
671
672 lock_sock(sk);
673
674 if (sk->sk_state == BT_CONNECT2 &&
675 test_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags)) {
676 hci_conn_accept(pi->conn->hcon, 0);
677 sk->sk_state = BT_CONFIG;
678
679 release_sock(sk);
680 return 0;
681 }
682
683 release_sock(sk);
684
685 return bt_sock_recvmsg(iocb, sock, msg, len, flags);
686}
687
665static int sco_sock_setsockopt(struct socket *sock, int level, int optname, char __user *optval, unsigned int optlen) 688static int sco_sock_setsockopt(struct socket *sock, int level, int optname, char __user *optval, unsigned int optlen)
666{ 689{
667 struct sock *sk = sock->sk; 690 struct sock *sk = sock->sk;
@@ -906,7 +929,10 @@ static void sco_conn_ready(struct sco_conn *conn)
906 hci_conn_hold(conn->hcon); 929 hci_conn_hold(conn->hcon);
907 __sco_chan_add(conn, sk, parent); 930 __sco_chan_add(conn, sk, parent);
908 931
909 sk->sk_state = BT_CONNECTED; 932 if (test_bit(BT_SK_DEFER_SETUP, &bt_sk(parent)->flags))
933 sk->sk_state = BT_CONNECT2;
934 else
935 sk->sk_state = BT_CONNECTED;
910 936
911 /* Wake up parent */ 937 /* Wake up parent */
912 parent->sk_data_ready(parent, 1); 938 parent->sk_data_ready(parent, 1);
@@ -919,7 +945,7 @@ done:
919} 945}
920 946
921/* ----- SCO interface with lower layer (HCI) ----- */ 947/* ----- SCO interface with lower layer (HCI) ----- */
922int sco_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr) 948int sco_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, __u8 *flags)
923{ 949{
924 struct sock *sk; 950 struct sock *sk;
925 struct hlist_node *node; 951 struct hlist_node *node;
@@ -936,6 +962,9 @@ int sco_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr)
936 if (!bacmp(&bt_sk(sk)->src, &hdev->bdaddr) || 962 if (!bacmp(&bt_sk(sk)->src, &hdev->bdaddr) ||
937 !bacmp(&bt_sk(sk)->src, BDADDR_ANY)) { 963 !bacmp(&bt_sk(sk)->src, BDADDR_ANY)) {
938 lm |= HCI_LM_ACCEPT; 964 lm |= HCI_LM_ACCEPT;
965
966 if (test_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags))
967 *flags |= HCI_PROTO_DEFER;
939 break; 968 break;
940 } 969 }
941 } 970 }
@@ -1024,7 +1053,7 @@ static const struct proto_ops sco_sock_ops = {
1024 .accept = sco_sock_accept, 1053 .accept = sco_sock_accept,
1025 .getname = sco_sock_getname, 1054 .getname = sco_sock_getname,
1026 .sendmsg = sco_sock_sendmsg, 1055 .sendmsg = sco_sock_sendmsg,
1027 .recvmsg = bt_sock_recvmsg, 1056 .recvmsg = sco_sock_recvmsg,
1028 .poll = bt_sock_poll, 1057 .poll = bt_sock_poll,
1029 .ioctl = bt_sock_ioctl, 1058 .ioctl = bt_sock_ioctl,
1030 .mmap = sock_no_mmap, 1059 .mmap = sock_no_mmap,