diff options
author | John W. Linville <linville@tuxdriver.com> | 2011-05-12 14:06:10 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2011-05-12 14:06:10 -0400 |
commit | 15cb309614f35df344b9f06a9ea9f077d1e449db (patch) | |
tree | 85e244564f42381be5bf9d81ed867bb793fa976d /net/bluetooth | |
parent | 4daf50f20256e0022c87c1609226e971a70c82fd (diff) | |
parent | 55183d06cd1bd939ceccdad628b0aae12c86b803 (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/padovan/bluetooth-next-2.6
Diffstat (limited to 'net/bluetooth')
-rw-r--r-- | net/bluetooth/hci_conn.c | 17 | ||||
-rw-r--r-- | net/bluetooth/hci_event.c | 5 | ||||
-rw-r--r-- | net/bluetooth/l2cap_core.c | 193 | ||||
-rw-r--r-- | net/bluetooth/l2cap_sock.c | 72 | ||||
-rw-r--r-- | net/bluetooth/mgmt.c | 3 | ||||
-rw-r--r-- | net/bluetooth/rfcomm/core.c | 2 |
6 files changed, 171 insertions, 121 deletions
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index 7f5ad8a2b22d..3163330cd4f1 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c | |||
@@ -623,6 +623,23 @@ encrypt: | |||
623 | } | 623 | } |
624 | EXPORT_SYMBOL(hci_conn_security); | 624 | EXPORT_SYMBOL(hci_conn_security); |
625 | 625 | ||
626 | /* Check secure link requirement */ | ||
627 | int hci_conn_check_secure(struct hci_conn *conn, __u8 sec_level) | ||
628 | { | ||
629 | BT_DBG("conn %p", conn); | ||
630 | |||
631 | if (sec_level != BT_SECURITY_HIGH) | ||
632 | return 1; /* Accept if non-secure is required */ | ||
633 | |||
634 | if (conn->key_type == HCI_LK_AUTH_COMBINATION || | ||
635 | (conn->key_type == HCI_LK_COMBINATION && | ||
636 | conn->pin_length == 16)) | ||
637 | return 1; | ||
638 | |||
639 | return 0; /* Reject not secure link */ | ||
640 | } | ||
641 | EXPORT_SYMBOL(hci_conn_check_secure); | ||
642 | |||
626 | /* Change link key */ | 643 | /* Change link key */ |
627 | int hci_conn_change_link_key(struct hci_conn *conn) | 644 | int hci_conn_change_link_key(struct hci_conn *conn) |
628 | { | 645 | { |
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index d5aa97ee6ffa..f13ddbf858ba 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c | |||
@@ -1440,7 +1440,7 @@ static inline void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff | |||
1440 | 1440 | ||
1441 | conn->state = BT_CLOSED; | 1441 | conn->state = BT_CLOSED; |
1442 | 1442 | ||
1443 | if (conn->type == ACL_LINK) | 1443 | if (conn->type == ACL_LINK || conn->type == LE_LINK) |
1444 | mgmt_disconnected(hdev->id, &conn->dst); | 1444 | mgmt_disconnected(hdev->id, &conn->dst); |
1445 | 1445 | ||
1446 | hci_proto_disconn_cfm(conn, ev->reason); | 1446 | hci_proto_disconn_cfm(conn, ev->reason); |
@@ -2659,12 +2659,15 @@ static inline void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff | |||
2659 | } | 2659 | } |
2660 | 2660 | ||
2661 | if (ev->status) { | 2661 | if (ev->status) { |
2662 | mgmt_connect_failed(hdev->id, &ev->bdaddr, ev->status); | ||
2662 | hci_proto_connect_cfm(conn, ev->status); | 2663 | hci_proto_connect_cfm(conn, ev->status); |
2663 | conn->state = BT_CLOSED; | 2664 | conn->state = BT_CLOSED; |
2664 | hci_conn_del(conn); | 2665 | hci_conn_del(conn); |
2665 | goto unlock; | 2666 | goto unlock; |
2666 | } | 2667 | } |
2667 | 2668 | ||
2669 | mgmt_connected(hdev->id, &ev->bdaddr); | ||
2670 | |||
2668 | conn->handle = __le16_to_cpu(ev->handle); | 2671 | conn->handle = __le16_to_cpu(ev->handle); |
2669 | conn->state = BT_CONNECTED; | 2672 | conn->state = BT_CONNECTED; |
2670 | 2673 | ||
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index 338d8c3eedab..a5ab4a29ae31 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c | |||
@@ -62,9 +62,8 @@ static u8 l2cap_fixed_chan[8] = { 0x02, }; | |||
62 | 62 | ||
63 | static struct workqueue_struct *_busy_wq; | 63 | static struct workqueue_struct *_busy_wq; |
64 | 64 | ||
65 | struct bt_sock_list l2cap_sk_list = { | 65 | LIST_HEAD(chan_list); |
66 | .lock = __RW_LOCK_UNLOCKED(l2cap_sk_list.lock) | 66 | DEFINE_RWLOCK(chan_list_lock); |
67 | }; | ||
68 | 67 | ||
69 | static void l2cap_busy_work(struct work_struct *work); | 68 | static void l2cap_busy_work(struct work_struct *work); |
70 | 69 | ||
@@ -135,6 +134,64 @@ static inline struct l2cap_chan *l2cap_get_chan_by_ident(struct l2cap_conn *conn | |||
135 | return c; | 134 | return c; |
136 | } | 135 | } |
137 | 136 | ||
137 | static struct l2cap_chan *__l2cap_global_chan_by_addr(__le16 psm, bdaddr_t *src) | ||
138 | { | ||
139 | struct l2cap_chan *c; | ||
140 | |||
141 | list_for_each_entry(c, &chan_list, global_l) { | ||
142 | if (c->sport == psm && !bacmp(&bt_sk(c->sk)->src, src)) | ||
143 | goto found; | ||
144 | } | ||
145 | |||
146 | c = NULL; | ||
147 | found: | ||
148 | return c; | ||
149 | } | ||
150 | |||
151 | int l2cap_add_psm(struct l2cap_chan *chan, bdaddr_t *src, __le16 psm) | ||
152 | { | ||
153 | int err; | ||
154 | |||
155 | write_lock_bh(&chan_list_lock); | ||
156 | |||
157 | if (psm && __l2cap_global_chan_by_addr(psm, src)) { | ||
158 | err = -EADDRINUSE; | ||
159 | goto done; | ||
160 | } | ||
161 | |||
162 | if (psm) { | ||
163 | chan->psm = psm; | ||
164 | chan->sport = psm; | ||
165 | err = 0; | ||
166 | } else { | ||
167 | u16 p; | ||
168 | |||
169 | err = -EINVAL; | ||
170 | for (p = 0x1001; p < 0x1100; p += 2) | ||
171 | if (!__l2cap_global_chan_by_addr(cpu_to_le16(p), src)) { | ||
172 | chan->psm = cpu_to_le16(p); | ||
173 | chan->sport = cpu_to_le16(p); | ||
174 | err = 0; | ||
175 | break; | ||
176 | } | ||
177 | } | ||
178 | |||
179 | done: | ||
180 | write_unlock_bh(&chan_list_lock); | ||
181 | return err; | ||
182 | } | ||
183 | |||
184 | int l2cap_add_scid(struct l2cap_chan *chan, __u16 scid) | ||
185 | { | ||
186 | write_lock_bh(&chan_list_lock); | ||
187 | |||
188 | chan->scid = scid; | ||
189 | |||
190 | write_unlock_bh(&chan_list_lock); | ||
191 | |||
192 | return 0; | ||
193 | } | ||
194 | |||
138 | static u16 l2cap_alloc_cid(struct l2cap_conn *conn) | 195 | static u16 l2cap_alloc_cid(struct l2cap_conn *conn) |
139 | { | 196 | { |
140 | u16 cid = L2CAP_CID_DYN_START; | 197 | u16 cid = L2CAP_CID_DYN_START; |
@@ -147,7 +204,7 @@ static u16 l2cap_alloc_cid(struct l2cap_conn *conn) | |||
147 | return 0; | 204 | return 0; |
148 | } | 205 | } |
149 | 206 | ||
150 | struct l2cap_chan *l2cap_chan_alloc(struct sock *sk) | 207 | struct l2cap_chan *l2cap_chan_create(struct sock *sk) |
151 | { | 208 | { |
152 | struct l2cap_chan *chan; | 209 | struct l2cap_chan *chan; |
153 | 210 | ||
@@ -157,11 +214,19 @@ struct l2cap_chan *l2cap_chan_alloc(struct sock *sk) | |||
157 | 214 | ||
158 | chan->sk = sk; | 215 | chan->sk = sk; |
159 | 216 | ||
217 | write_lock_bh(&chan_list_lock); | ||
218 | list_add(&chan->global_l, &chan_list); | ||
219 | write_unlock_bh(&chan_list_lock); | ||
220 | |||
160 | return chan; | 221 | return chan; |
161 | } | 222 | } |
162 | 223 | ||
163 | void l2cap_chan_free(struct l2cap_chan *chan) | 224 | void l2cap_chan_destroy(struct l2cap_chan *chan) |
164 | { | 225 | { |
226 | write_lock_bh(&chan_list_lock); | ||
227 | list_del(&chan->global_l); | ||
228 | write_unlock_bh(&chan_list_lock); | ||
229 | |||
165 | kfree(chan); | 230 | kfree(chan); |
166 | } | 231 | } |
167 | 232 | ||
@@ -591,48 +656,51 @@ static void l2cap_conn_start(struct l2cap_conn *conn) | |||
591 | /* Find socket with cid and source bdaddr. | 656 | /* Find socket with cid and source bdaddr. |
592 | * Returns closest match, locked. | 657 | * Returns closest match, locked. |
593 | */ | 658 | */ |
594 | static struct sock *l2cap_get_sock_by_scid(int state, __le16 cid, bdaddr_t *src) | 659 | static struct l2cap_chan *l2cap_global_chan_by_scid(int state, __le16 cid, bdaddr_t *src) |
595 | { | 660 | { |
596 | struct sock *sk = NULL, *sk1 = NULL; | 661 | struct l2cap_chan *c, *c1 = NULL; |
597 | struct hlist_node *node; | ||
598 | 662 | ||
599 | read_lock(&l2cap_sk_list.lock); | 663 | read_lock(&chan_list_lock); |
600 | 664 | ||
601 | sk_for_each(sk, node, &l2cap_sk_list.head) { | 665 | list_for_each_entry(c, &chan_list, global_l) { |
602 | struct l2cap_chan *chan = l2cap_pi(sk)->chan; | 666 | struct sock *sk = c->sk; |
603 | 667 | ||
604 | if (state && sk->sk_state != state) | 668 | if (state && sk->sk_state != state) |
605 | continue; | 669 | continue; |
606 | 670 | ||
607 | if (chan->scid == cid) { | 671 | if (c->scid == cid) { |
608 | /* Exact match. */ | 672 | /* Exact match. */ |
609 | if (!bacmp(&bt_sk(sk)->src, src)) | 673 | if (!bacmp(&bt_sk(sk)->src, src)) { |
610 | break; | 674 | read_unlock(&chan_list_lock); |
675 | return c; | ||
676 | } | ||
611 | 677 | ||
612 | /* Closest match */ | 678 | /* Closest match */ |
613 | if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY)) | 679 | if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY)) |
614 | sk1 = sk; | 680 | c1 = c; |
615 | } | 681 | } |
616 | } | 682 | } |
617 | 683 | ||
618 | read_unlock(&l2cap_sk_list.lock); | 684 | read_unlock(&chan_list_lock); |
619 | 685 | ||
620 | return node ? sk : sk1; | 686 | return c1; |
621 | } | 687 | } |
622 | 688 | ||
623 | static void l2cap_le_conn_ready(struct l2cap_conn *conn) | 689 | static void l2cap_le_conn_ready(struct l2cap_conn *conn) |
624 | { | 690 | { |
625 | struct sock *parent, *sk; | 691 | struct sock *parent, *sk; |
626 | struct l2cap_chan *chan; | 692 | struct l2cap_chan *chan, *pchan; |
627 | 693 | ||
628 | BT_DBG(""); | 694 | BT_DBG(""); |
629 | 695 | ||
630 | /* Check if we have socket listening on cid */ | 696 | /* Check if we have socket listening on cid */ |
631 | parent = l2cap_get_sock_by_scid(BT_LISTEN, L2CAP_CID_LE_DATA, | 697 | pchan = l2cap_global_chan_by_scid(BT_LISTEN, L2CAP_CID_LE_DATA, |
632 | conn->src); | 698 | conn->src); |
633 | if (!parent) | 699 | if (!pchan) |
634 | return; | 700 | return; |
635 | 701 | ||
702 | parent = pchan->sk; | ||
703 | |||
636 | bh_lock_sock(parent); | 704 | bh_lock_sock(parent); |
637 | 705 | ||
638 | /* Check for backlog size */ | 706 | /* Check for backlog size */ |
@@ -645,7 +713,7 @@ static void l2cap_le_conn_ready(struct l2cap_conn *conn) | |||
645 | if (!sk) | 713 | if (!sk) |
646 | goto clean; | 714 | goto clean; |
647 | 715 | ||
648 | chan = l2cap_chan_alloc(sk); | 716 | chan = l2cap_chan_create(sk); |
649 | if (!chan) { | 717 | if (!chan) { |
650 | l2cap_sock_kill(sk); | 718 | l2cap_sock_kill(sk); |
651 | goto clean; | 719 | goto clean; |
@@ -823,33 +891,34 @@ static inline void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *ch | |||
823 | /* Find socket with psm and source bdaddr. | 891 | /* Find socket with psm and source bdaddr. |
824 | * Returns closest match. | 892 | * Returns closest match. |
825 | */ | 893 | */ |
826 | static struct sock *l2cap_get_sock_by_psm(int state, __le16 psm, bdaddr_t *src) | 894 | static struct l2cap_chan *l2cap_global_chan_by_psm(int state, __le16 psm, bdaddr_t *src) |
827 | { | 895 | { |
828 | struct sock *sk = NULL, *sk1 = NULL; | 896 | struct l2cap_chan *c, *c1 = NULL; |
829 | struct hlist_node *node; | ||
830 | 897 | ||
831 | read_lock(&l2cap_sk_list.lock); | 898 | read_lock(&chan_list_lock); |
832 | 899 | ||
833 | sk_for_each(sk, node, &l2cap_sk_list.head) { | 900 | list_for_each_entry(c, &chan_list, global_l) { |
834 | struct l2cap_chan *chan = l2cap_pi(sk)->chan; | 901 | struct sock *sk = c->sk; |
835 | 902 | ||
836 | if (state && sk->sk_state != state) | 903 | if (state && sk->sk_state != state) |
837 | continue; | 904 | continue; |
838 | 905 | ||
839 | if (chan->psm == psm) { | 906 | if (c->psm == psm) { |
840 | /* Exact match. */ | 907 | /* Exact match. */ |
841 | if (!bacmp(&bt_sk(sk)->src, src)) | 908 | if (!bacmp(&bt_sk(sk)->src, src)) { |
842 | break; | 909 | read_unlock_bh(&chan_list_lock); |
910 | return c; | ||
911 | } | ||
843 | 912 | ||
844 | /* Closest match */ | 913 | /* Closest match */ |
845 | if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY)) | 914 | if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY)) |
846 | sk1 = sk; | 915 | c1 = c; |
847 | } | 916 | } |
848 | } | 917 | } |
849 | 918 | ||
850 | read_unlock(&l2cap_sk_list.lock); | 919 | read_unlock(&chan_list_lock); |
851 | 920 | ||
852 | return node ? sk : sk1; | 921 | return c1; |
853 | } | 922 | } |
854 | 923 | ||
855 | int l2cap_chan_connect(struct l2cap_chan *chan) | 924 | int l2cap_chan_connect(struct l2cap_chan *chan) |
@@ -2019,7 +2088,7 @@ static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hd | |||
2019 | { | 2088 | { |
2020 | struct l2cap_conn_req *req = (struct l2cap_conn_req *) data; | 2089 | struct l2cap_conn_req *req = (struct l2cap_conn_req *) data; |
2021 | struct l2cap_conn_rsp rsp; | 2090 | struct l2cap_conn_rsp rsp; |
2022 | struct l2cap_chan *chan = NULL; | 2091 | struct l2cap_chan *chan = NULL, *pchan; |
2023 | struct sock *parent, *sk = NULL; | 2092 | struct sock *parent, *sk = NULL; |
2024 | int result, status = L2CAP_CS_NO_INFO; | 2093 | int result, status = L2CAP_CS_NO_INFO; |
2025 | 2094 | ||
@@ -2029,12 +2098,14 @@ static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hd | |||
2029 | BT_DBG("psm 0x%2.2x scid 0x%4.4x", psm, scid); | 2098 | BT_DBG("psm 0x%2.2x scid 0x%4.4x", psm, scid); |
2030 | 2099 | ||
2031 | /* Check if we have socket listening on psm */ | 2100 | /* Check if we have socket listening on psm */ |
2032 | parent = l2cap_get_sock_by_psm(BT_LISTEN, psm, conn->src); | 2101 | pchan = l2cap_global_chan_by_psm(BT_LISTEN, psm, conn->src); |
2033 | if (!parent) { | 2102 | if (!pchan) { |
2034 | result = L2CAP_CR_BAD_PSM; | 2103 | result = L2CAP_CR_BAD_PSM; |
2035 | goto sendresp; | 2104 | goto sendresp; |
2036 | } | 2105 | } |
2037 | 2106 | ||
2107 | parent = pchan->sk; | ||
2108 | |||
2038 | bh_lock_sock(parent); | 2109 | bh_lock_sock(parent); |
2039 | 2110 | ||
2040 | /* Check if the ACL is secure enough (if not SDP) */ | 2111 | /* Check if the ACL is secure enough (if not SDP) */ |
@@ -2057,7 +2128,7 @@ static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hd | |||
2057 | if (!sk) | 2128 | if (!sk) |
2058 | goto response; | 2129 | goto response; |
2059 | 2130 | ||
2060 | chan = l2cap_chan_alloc(sk); | 2131 | chan = l2cap_chan_create(sk); |
2061 | if (!chan) { | 2132 | if (!chan) { |
2062 | l2cap_sock_kill(sk); | 2133 | l2cap_sock_kill(sk); |
2063 | goto response; | 2134 | goto response; |
@@ -3685,11 +3756,14 @@ done: | |||
3685 | static inline int l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm, struct sk_buff *skb) | 3756 | static inline int l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm, struct sk_buff *skb) |
3686 | { | 3757 | { |
3687 | struct sock *sk; | 3758 | struct sock *sk; |
3759 | struct l2cap_chan *chan; | ||
3688 | 3760 | ||
3689 | sk = l2cap_get_sock_by_psm(0, psm, conn->src); | 3761 | chan = l2cap_global_chan_by_psm(0, psm, conn->src); |
3690 | if (!sk) | 3762 | if (!chan) |
3691 | goto drop; | 3763 | goto drop; |
3692 | 3764 | ||
3765 | sk = chan->sk; | ||
3766 | |||
3693 | bh_lock_sock(sk); | 3767 | bh_lock_sock(sk); |
3694 | 3768 | ||
3695 | BT_DBG("sk %p, len %d", sk, skb->len); | 3769 | BT_DBG("sk %p, len %d", sk, skb->len); |
@@ -3715,11 +3789,14 @@ done: | |||
3715 | static inline int l2cap_att_channel(struct l2cap_conn *conn, __le16 cid, struct sk_buff *skb) | 3789 | static inline int l2cap_att_channel(struct l2cap_conn *conn, __le16 cid, struct sk_buff *skb) |
3716 | { | 3790 | { |
3717 | struct sock *sk; | 3791 | struct sock *sk; |
3792 | struct l2cap_chan *chan; | ||
3718 | 3793 | ||
3719 | sk = l2cap_get_sock_by_scid(0, cid, conn->src); | 3794 | chan = l2cap_global_chan_by_scid(0, cid, conn->src); |
3720 | if (!sk) | 3795 | if (!chan) |
3721 | goto drop; | 3796 | goto drop; |
3722 | 3797 | ||
3798 | sk = chan->sk; | ||
3799 | |||
3723 | bh_lock_sock(sk); | 3800 | bh_lock_sock(sk); |
3724 | 3801 | ||
3725 | BT_DBG("sk %p, len %d", sk, skb->len); | 3802 | BT_DBG("sk %p, len %d", sk, skb->len); |
@@ -3786,8 +3863,7 @@ static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb) | |||
3786 | static int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type) | 3863 | static int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type) |
3787 | { | 3864 | { |
3788 | int exact = 0, lm1 = 0, lm2 = 0; | 3865 | int exact = 0, lm1 = 0, lm2 = 0; |
3789 | register struct sock *sk; | 3866 | struct l2cap_chan *c; |
3790 | struct hlist_node *node; | ||
3791 | 3867 | ||
3792 | if (type != ACL_LINK) | 3868 | if (type != ACL_LINK) |
3793 | return -EINVAL; | 3869 | return -EINVAL; |
@@ -3795,25 +3871,25 @@ static int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type) | |||
3795 | BT_DBG("hdev %s, bdaddr %s", hdev->name, batostr(bdaddr)); | 3871 | BT_DBG("hdev %s, bdaddr %s", hdev->name, batostr(bdaddr)); |
3796 | 3872 | ||
3797 | /* Find listening sockets and check their link_mode */ | 3873 | /* Find listening sockets and check their link_mode */ |
3798 | read_lock(&l2cap_sk_list.lock); | 3874 | read_lock(&chan_list_lock); |
3799 | sk_for_each(sk, node, &l2cap_sk_list.head) { | 3875 | list_for_each_entry(c, &chan_list, global_l) { |
3800 | struct l2cap_chan *chan = l2cap_pi(sk)->chan; | 3876 | struct sock *sk = c->sk; |
3801 | 3877 | ||
3802 | if (sk->sk_state != BT_LISTEN) | 3878 | if (sk->sk_state != BT_LISTEN) |
3803 | continue; | 3879 | continue; |
3804 | 3880 | ||
3805 | if (!bacmp(&bt_sk(sk)->src, &hdev->bdaddr)) { | 3881 | if (!bacmp(&bt_sk(sk)->src, &hdev->bdaddr)) { |
3806 | lm1 |= HCI_LM_ACCEPT; | 3882 | lm1 |= HCI_LM_ACCEPT; |
3807 | if (chan->role_switch) | 3883 | if (c->role_switch) |
3808 | lm1 |= HCI_LM_MASTER; | 3884 | lm1 |= HCI_LM_MASTER; |
3809 | exact++; | 3885 | exact++; |
3810 | } else if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY)) { | 3886 | } else if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY)) { |
3811 | lm2 |= HCI_LM_ACCEPT; | 3887 | lm2 |= HCI_LM_ACCEPT; |
3812 | if (chan->role_switch) | 3888 | if (c->role_switch) |
3813 | lm2 |= HCI_LM_MASTER; | 3889 | lm2 |= HCI_LM_MASTER; |
3814 | } | 3890 | } |
3815 | } | 3891 | } |
3816 | read_unlock(&l2cap_sk_list.lock); | 3892 | read_unlock(&chan_list_lock); |
3817 | 3893 | ||
3818 | return exact ? lm1 : lm2; | 3894 | return exact ? lm1 : lm2; |
3819 | } | 3895 | } |
@@ -4066,25 +4142,22 @@ drop: | |||
4066 | 4142 | ||
4067 | static int l2cap_debugfs_show(struct seq_file *f, void *p) | 4143 | static int l2cap_debugfs_show(struct seq_file *f, void *p) |
4068 | { | 4144 | { |
4069 | struct sock *sk; | 4145 | struct l2cap_chan *c; |
4070 | struct hlist_node *node; | ||
4071 | 4146 | ||
4072 | read_lock_bh(&l2cap_sk_list.lock); | 4147 | read_lock_bh(&chan_list_lock); |
4073 | 4148 | ||
4074 | sk_for_each(sk, node, &l2cap_sk_list.head) { | 4149 | list_for_each_entry(c, &chan_list, global_l) { |
4075 | struct l2cap_pinfo *pi = l2cap_pi(sk); | 4150 | struct sock *sk = c->sk; |
4076 | struct l2cap_chan *chan = pi->chan; | ||
4077 | 4151 | ||
4078 | seq_printf(f, "%s %s %d %d 0x%4.4x 0x%4.4x %d %d %d %d\n", | 4152 | seq_printf(f, "%s %s %d %d 0x%4.4x 0x%4.4x %d %d %d %d\n", |
4079 | batostr(&bt_sk(sk)->src), | 4153 | batostr(&bt_sk(sk)->src), |
4080 | batostr(&bt_sk(sk)->dst), | 4154 | batostr(&bt_sk(sk)->dst), |
4081 | sk->sk_state, __le16_to_cpu(chan->psm), | 4155 | sk->sk_state, __le16_to_cpu(c->psm), |
4082 | chan->scid, chan->dcid, | 4156 | c->scid, c->dcid, c->imtu, c->omtu, |
4083 | chan->imtu, chan->omtu, chan->sec_level, | 4157 | c->sec_level, c->mode); |
4084 | chan->mode); | ||
4085 | } | 4158 | } |
4086 | 4159 | ||
4087 | read_unlock_bh(&l2cap_sk_list.lock); | 4160 | read_unlock_bh(&chan_list_lock); |
4088 | 4161 | ||
4089 | return 0; | 4162 | return 0; |
4090 | } | 4163 | } |
diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index 09cc7a005349..c98360d40b84 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c | |||
@@ -78,22 +78,6 @@ void l2cap_sock_clear_timer(struct sock *sk) | |||
78 | sk_stop_timer(sk, &sk->sk_timer); | 78 | sk_stop_timer(sk, &sk->sk_timer); |
79 | } | 79 | } |
80 | 80 | ||
81 | static struct sock *__l2cap_get_sock_by_addr(__le16 psm, bdaddr_t *src) | ||
82 | { | ||
83 | struct sock *sk; | ||
84 | struct hlist_node *node; | ||
85 | sk_for_each(sk, node, &l2cap_sk_list.head) { | ||
86 | struct l2cap_chan *chan = l2cap_pi(sk)->chan; | ||
87 | |||
88 | if (chan->sport == psm && !bacmp(&bt_sk(sk)->src, src)) | ||
89 | goto found; | ||
90 | } | ||
91 | |||
92 | sk = NULL; | ||
93 | found: | ||
94 | return sk; | ||
95 | } | ||
96 | |||
97 | static int l2cap_sock_bind(struct socket *sock, struct sockaddr *addr, int alen) | 81 | static int l2cap_sock_bind(struct socket *sock, struct sockaddr *addr, int alen) |
98 | { | 82 | { |
99 | struct sock *sk = sock->sk; | 83 | struct sock *sk = sock->sk; |
@@ -136,26 +120,20 @@ static int l2cap_sock_bind(struct socket *sock, struct sockaddr *addr, int alen) | |||
136 | } | 120 | } |
137 | } | 121 | } |
138 | 122 | ||
139 | write_lock_bh(&l2cap_sk_list.lock); | 123 | if (la.l2_cid) |
124 | err = l2cap_add_scid(chan, la.l2_cid); | ||
125 | else | ||
126 | err = l2cap_add_psm(chan, &la.l2_bdaddr, la.l2_psm); | ||
140 | 127 | ||
141 | if (la.l2_psm && __l2cap_get_sock_by_addr(la.l2_psm, &la.l2_bdaddr)) { | 128 | if (err < 0) |
142 | err = -EADDRINUSE; | 129 | goto done; |
143 | } else { | ||
144 | /* Save source address */ | ||
145 | bacpy(&bt_sk(sk)->src, &la.l2_bdaddr); | ||
146 | chan->psm = la.l2_psm; | ||
147 | chan->sport = la.l2_psm; | ||
148 | sk->sk_state = BT_BOUND; | ||
149 | |||
150 | if (__le16_to_cpu(la.l2_psm) == 0x0001 || | ||
151 | __le16_to_cpu(la.l2_psm) == 0x0003) | ||
152 | chan->sec_level = BT_SECURITY_SDP; | ||
153 | } | ||
154 | 130 | ||
155 | if (la.l2_cid) | 131 | if (__le16_to_cpu(la.l2_psm) == 0x0001 || |
156 | chan->scid = la.l2_cid; | 132 | __le16_to_cpu(la.l2_psm) == 0x0003) |
133 | chan->sec_level = BT_SECURITY_SDP; | ||
157 | 134 | ||
158 | write_unlock_bh(&l2cap_sk_list.lock); | 135 | bacpy(&bt_sk(sk)->src, &la.l2_bdaddr); |
136 | sk->sk_state = BT_BOUND; | ||
159 | 137 | ||
160 | done: | 138 | done: |
161 | release_sock(sk); | 139 | release_sock(sk); |
@@ -278,28 +256,6 @@ static int l2cap_sock_listen(struct socket *sock, int backlog) | |||
278 | goto done; | 256 | goto done; |
279 | } | 257 | } |
280 | 258 | ||
281 | if (!chan->psm && !chan->scid) { | ||
282 | bdaddr_t *src = &bt_sk(sk)->src; | ||
283 | u16 psm; | ||
284 | |||
285 | err = -EINVAL; | ||
286 | |||
287 | write_lock_bh(&l2cap_sk_list.lock); | ||
288 | |||
289 | for (psm = 0x1001; psm < 0x1100; psm += 2) | ||
290 | if (!__l2cap_get_sock_by_addr(cpu_to_le16(psm), src)) { | ||
291 | chan->psm = cpu_to_le16(psm); | ||
292 | chan->sport = cpu_to_le16(psm); | ||
293 | err = 0; | ||
294 | break; | ||
295 | } | ||
296 | |||
297 | write_unlock_bh(&l2cap_sk_list.lock); | ||
298 | |||
299 | if (err < 0) | ||
300 | goto done; | ||
301 | } | ||
302 | |||
303 | sk->sk_max_ack_backlog = backlog; | 259 | sk->sk_max_ack_backlog = backlog; |
304 | sk->sk_ack_backlog = 0; | 260 | sk->sk_ack_backlog = 0; |
305 | sk->sk_state = BT_LISTEN; | 261 | sk->sk_state = BT_LISTEN; |
@@ -852,8 +808,7 @@ void l2cap_sock_kill(struct sock *sk) | |||
852 | 808 | ||
853 | /* Kill poor orphan */ | 809 | /* Kill poor orphan */ |
854 | 810 | ||
855 | l2cap_chan_free(l2cap_pi(sk)->chan); | 811 | l2cap_chan_destroy(l2cap_pi(sk)->chan); |
856 | bt_sock_unlink(&l2cap_sk_list, sk); | ||
857 | sock_set_flag(sk, SOCK_DEAD); | 812 | sock_set_flag(sk, SOCK_DEAD); |
858 | sock_put(sk); | 813 | sock_put(sk); |
859 | } | 814 | } |
@@ -1069,7 +1024,6 @@ struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock, int proto, g | |||
1069 | 1024 | ||
1070 | setup_timer(&sk->sk_timer, l2cap_sock_timeout, (unsigned long) sk); | 1025 | setup_timer(&sk->sk_timer, l2cap_sock_timeout, (unsigned long) sk); |
1071 | 1026 | ||
1072 | bt_sock_link(&l2cap_sk_list, sk); | ||
1073 | return sk; | 1027 | return sk; |
1074 | } | 1028 | } |
1075 | 1029 | ||
@@ -1096,7 +1050,7 @@ static int l2cap_sock_create(struct net *net, struct socket *sock, int protocol, | |||
1096 | if (!sk) | 1050 | if (!sk) |
1097 | return -ENOMEM; | 1051 | return -ENOMEM; |
1098 | 1052 | ||
1099 | chan = l2cap_chan_alloc(sk); | 1053 | chan = l2cap_chan_create(sk); |
1100 | if (!chan) { | 1054 | if (!chan) { |
1101 | l2cap_sock_kill(sk); | 1055 | l2cap_sock_kill(sk); |
1102 | return -ENOMEM; | 1056 | return -ENOMEM; |
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 2481d257ed98..dae382ce7020 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c | |||
@@ -1033,6 +1033,9 @@ static int disconnect(struct sock *sk, u16 index, unsigned char *data, u16 len) | |||
1033 | } | 1033 | } |
1034 | 1034 | ||
1035 | conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr); | 1035 | conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr); |
1036 | if (!conn) | ||
1037 | conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->bdaddr); | ||
1038 | |||
1036 | if (!conn) { | 1039 | if (!conn) { |
1037 | err = cmd_status(sk, index, MGMT_OP_DISCONNECT, ENOTCONN); | 1040 | err = cmd_status(sk, index, MGMT_OP_DISCONNECT, ENOTCONN); |
1038 | goto failed; | 1041 | goto failed; |
diff --git a/net/bluetooth/rfcomm/core.c b/net/bluetooth/rfcomm/core.c index 121a5c13b989..5759bb7054f7 100644 --- a/net/bluetooth/rfcomm/core.c +++ b/net/bluetooth/rfcomm/core.c | |||
@@ -2096,7 +2096,7 @@ static void rfcomm_security_cfm(struct hci_conn *conn, u8 status, u8 encrypt) | |||
2096 | if (!test_and_clear_bit(RFCOMM_AUTH_PENDING, &d->flags)) | 2096 | if (!test_and_clear_bit(RFCOMM_AUTH_PENDING, &d->flags)) |
2097 | continue; | 2097 | continue; |
2098 | 2098 | ||
2099 | if (!status) | 2099 | if (!status && hci_conn_check_secure(conn, d->sec_level)) |
2100 | set_bit(RFCOMM_AUTH_ACCEPT, &d->flags); | 2100 | set_bit(RFCOMM_AUTH_ACCEPT, &d->flags); |
2101 | else | 2101 | else |
2102 | set_bit(RFCOMM_AUTH_REJECT, &d->flags); | 2102 | set_bit(RFCOMM_AUTH_REJECT, &d->flags); |