diff options
author | Gustavo F. Padovan <padovan@profusion.mobi> | 2011-03-24 23:22:30 -0400 |
---|---|---|
committer | Gustavo F. Padovan <padovan@profusion.mobi> | 2011-04-07 17:06:25 -0400 |
commit | 48454079c2d4b9ee65c570a22c5fdfe1827996a4 (patch) | |
tree | 9476bb42ae7eac59ac53688a267c4cc0f7b13b86 | |
parent | db940cb0db7c69a217661ecd49e1e6b0d680a6cc (diff) |
Bluetooth: Create struct l2cap_chan
struct l2cap_chan cames to create a clear separation between what
properties and data belongs to the L2CAP channel and what belongs to the
socket. By now we just fold the struct sock * in struct l2cap_chan as all
the channel info is struct l2cap_pinfo today.
In the next commits we will see a move of channel stuff to struct
l2cap_chan.
Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi>
-rw-r--r-- | include/net/bluetooth/l2cap.h | 18 | ||||
-rw-r--r-- | net/bluetooth/l2cap_core.c | 247 | ||||
-rw-r--r-- | net/bluetooth/l2cap_sock.c | 6 |
3 files changed, 175 insertions, 96 deletions
diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h index 2b9ca0d5c4a0..6378bcc94e2b 100644 --- a/include/net/bluetooth/l2cap.h +++ b/include/net/bluetooth/l2cap.h | |||
@@ -276,9 +276,16 @@ struct l2cap_conn_param_update_rsp { | |||
276 | #define L2CAP_CONN_PARAM_ACCEPTED 0x0000 | 276 | #define L2CAP_CONN_PARAM_ACCEPTED 0x0000 |
277 | #define L2CAP_CONN_PARAM_REJECTED 0x0001 | 277 | #define L2CAP_CONN_PARAM_REJECTED 0x0001 |
278 | 278 | ||
279 | /* ----- L2CAP connections ----- */ | 279 | /* ----- L2CAP channels and connections ----- */ |
280 | |||
281 | struct l2cap_chan { | ||
282 | struct sock *sk; | ||
283 | struct l2cap_chan *next_c; | ||
284 | struct l2cap_chan *prev_c; | ||
285 | }; | ||
286 | |||
280 | struct l2cap_chan_list { | 287 | struct l2cap_chan_list { |
281 | struct sock *head; | 288 | struct l2cap_chan *head; |
282 | rwlock_t lock; | 289 | rwlock_t lock; |
283 | }; | 290 | }; |
284 | 291 | ||
@@ -317,7 +324,7 @@ struct sock_del_list { | |||
317 | #define L2CAP_INFO_FEAT_MASK_REQ_SENT 0x04 | 324 | #define L2CAP_INFO_FEAT_MASK_REQ_SENT 0x04 |
318 | #define L2CAP_INFO_FEAT_MASK_REQ_DONE 0x08 | 325 | #define L2CAP_INFO_FEAT_MASK_REQ_DONE 0x08 |
319 | 326 | ||
320 | /* ----- L2CAP channel and socket info ----- */ | 327 | /* ----- L2CAP socket info ----- */ |
321 | #define l2cap_pi(sk) ((struct l2cap_pinfo *) sk) | 328 | #define l2cap_pi(sk) ((struct l2cap_pinfo *) sk) |
322 | #define TX_QUEUE(sk) (&l2cap_pi(sk)->tx_queue) | 329 | #define TX_QUEUE(sk) (&l2cap_pi(sk)->tx_queue) |
323 | #define SREJ_QUEUE(sk) (&l2cap_pi(sk)->srej_queue) | 330 | #define SREJ_QUEUE(sk) (&l2cap_pi(sk)->srej_queue) |
@@ -389,8 +396,7 @@ struct l2cap_pinfo { | |||
389 | struct work_struct busy_work; | 396 | struct work_struct busy_work; |
390 | struct srej_list srej_l; | 397 | struct srej_list srej_l; |
391 | struct l2cap_conn *conn; | 398 | struct l2cap_conn *conn; |
392 | struct sock *next_c; | 399 | struct l2cap_chan *chan; |
393 | struct sock *prev_c; | ||
394 | }; | 400 | }; |
395 | 401 | ||
396 | #define L2CAP_CONF_REQ_SENT 0x01 | 402 | #define L2CAP_CONF_REQ_SENT 0x01 |
@@ -471,7 +477,7 @@ void l2cap_sock_init(struct sock *sk, struct sock *parent); | |||
471 | struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock, | 477 | struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock, |
472 | int proto, gfp_t prio); | 478 | int proto, gfp_t prio); |
473 | void l2cap_send_disconn_req(struct l2cap_conn *conn, struct sock *sk, int err); | 479 | void l2cap_send_disconn_req(struct l2cap_conn *conn, struct sock *sk, int err); |
474 | void l2cap_chan_del(struct sock *sk, int err); | 480 | void l2cap_chan_del(struct l2cap_chan *chan, int err); |
475 | int l2cap_do_connect(struct sock *sk); | 481 | int l2cap_do_connect(struct sock *sk); |
476 | 482 | ||
477 | #endif /* __L2CAP_H */ | 483 | #endif /* __L2CAP_H */ |
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index c3cebed205cc..e49d8f7b80a5 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c | |||
@@ -74,58 +74,58 @@ static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn, | |||
74 | static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb); | 74 | static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb); |
75 | 75 | ||
76 | /* ---- L2CAP channels ---- */ | 76 | /* ---- L2CAP channels ---- */ |
77 | static struct sock *__l2cap_get_chan_by_dcid(struct l2cap_chan_list *l, u16 cid) | 77 | static struct l2cap_chan *__l2cap_get_chan_by_dcid(struct l2cap_chan_list *l, u16 cid) |
78 | { | 78 | { |
79 | struct sock *s; | 79 | struct l2cap_chan *c; |
80 | for (s = l->head; s; s = l2cap_pi(s)->next_c) { | 80 | for (c = l->head; c; c = c->next_c) { |
81 | if (l2cap_pi(s)->dcid == cid) | 81 | if (l2cap_pi(c->sk)->dcid == cid) |
82 | break; | 82 | break; |
83 | } | 83 | } |
84 | return s; | 84 | return c; |
85 | } | 85 | } |
86 | 86 | ||
87 | static struct sock *__l2cap_get_chan_by_scid(struct l2cap_chan_list *l, u16 cid) | 87 | static struct l2cap_chan *__l2cap_get_chan_by_scid(struct l2cap_chan_list *l, u16 cid) |
88 | { | 88 | { |
89 | struct sock *s; | 89 | struct l2cap_chan *c; |
90 | for (s = l->head; s; s = l2cap_pi(s)->next_c) { | 90 | for (c = l->head; c; c = c->next_c) { |
91 | if (l2cap_pi(s)->scid == cid) | 91 | if (l2cap_pi(c->sk)->scid == cid) |
92 | break; | 92 | break; |
93 | } | 93 | } |
94 | return s; | 94 | return c; |
95 | } | 95 | } |
96 | 96 | ||
97 | /* Find channel with given SCID. | 97 | /* Find channel with given SCID. |
98 | * Returns locked socket */ | 98 | * Returns locked socket */ |
99 | static inline struct sock *l2cap_get_chan_by_scid(struct l2cap_chan_list *l, u16 cid) | 99 | static inline struct l2cap_chan *l2cap_get_chan_by_scid(struct l2cap_chan_list *l, u16 cid) |
100 | { | 100 | { |
101 | struct sock *s; | 101 | struct l2cap_chan *c; |
102 | read_lock(&l->lock); | 102 | read_lock(&l->lock); |
103 | s = __l2cap_get_chan_by_scid(l, cid); | 103 | c = __l2cap_get_chan_by_scid(l, cid); |
104 | if (s) | 104 | if (c) |
105 | bh_lock_sock(s); | 105 | bh_lock_sock(c->sk); |
106 | read_unlock(&l->lock); | 106 | read_unlock(&l->lock); |
107 | return s; | 107 | return c; |
108 | } | 108 | } |
109 | 109 | ||
110 | static struct sock *__l2cap_get_chan_by_ident(struct l2cap_chan_list *l, u8 ident) | 110 | static struct l2cap_chan *__l2cap_get_chan_by_ident(struct l2cap_chan_list *l, u8 ident) |
111 | { | 111 | { |
112 | struct sock *s; | 112 | struct l2cap_chan *c; |
113 | for (s = l->head; s; s = l2cap_pi(s)->next_c) { | 113 | for (c = l->head; c; c = c->next_c) { |
114 | if (l2cap_pi(s)->ident == ident) | 114 | if (l2cap_pi(c->sk)->ident == ident) |
115 | break; | 115 | break; |
116 | } | 116 | } |
117 | return s; | 117 | return c; |
118 | } | 118 | } |
119 | 119 | ||
120 | static inline struct sock *l2cap_get_chan_by_ident(struct l2cap_chan_list *l, u8 ident) | 120 | static inline struct l2cap_chan *l2cap_get_chan_by_ident(struct l2cap_chan_list *l, u8 ident) |
121 | { | 121 | { |
122 | struct sock *s; | 122 | struct l2cap_chan *c; |
123 | read_lock(&l->lock); | 123 | read_lock(&l->lock); |
124 | s = __l2cap_get_chan_by_ident(l, ident); | 124 | c = __l2cap_get_chan_by_ident(l, ident); |
125 | if (s) | 125 | if (c) |
126 | bh_lock_sock(s); | 126 | bh_lock_sock(c->sk); |
127 | read_unlock(&l->lock); | 127 | read_unlock(&l->lock); |
128 | return s; | 128 | return c; |
129 | } | 129 | } |
130 | 130 | ||
131 | static u16 l2cap_alloc_cid(struct l2cap_chan_list *l) | 131 | static u16 l2cap_alloc_cid(struct l2cap_chan_list *l) |
@@ -140,38 +140,52 @@ static u16 l2cap_alloc_cid(struct l2cap_chan_list *l) | |||
140 | return 0; | 140 | return 0; |
141 | } | 141 | } |
142 | 142 | ||
143 | static inline void __l2cap_chan_link(struct l2cap_chan_list *l, struct sock *sk) | 143 | static struct l2cap_chan *l2cap_chan_alloc(struct sock *sk) |
144 | { | ||
145 | struct l2cap_chan *chan; | ||
146 | |||
147 | chan = kzalloc(sizeof(*chan), GFP_ATOMIC); | ||
148 | if (!chan) | ||
149 | return NULL; | ||
150 | |||
151 | chan->sk = sk; | ||
152 | |||
153 | return chan; | ||
154 | } | ||
155 | |||
156 | static inline void __l2cap_chan_link(struct l2cap_chan_list *l, struct l2cap_chan *chan) | ||
144 | { | 157 | { |
145 | sock_hold(sk); | 158 | sock_hold(chan->sk); |
146 | 159 | ||
147 | if (l->head) | 160 | if (l->head) |
148 | l2cap_pi(l->head)->prev_c = sk; | 161 | l->head->prev_c = chan; |
149 | 162 | ||
150 | l2cap_pi(sk)->next_c = l->head; | 163 | chan->next_c = l->head; |
151 | l2cap_pi(sk)->prev_c = NULL; | 164 | chan->prev_c = NULL; |
152 | l->head = sk; | 165 | l->head = chan; |
153 | } | 166 | } |
154 | 167 | ||
155 | static inline void l2cap_chan_unlink(struct l2cap_chan_list *l, struct sock *sk) | 168 | static inline void l2cap_chan_unlink(struct l2cap_chan_list *l, struct l2cap_chan *chan) |
156 | { | 169 | { |
157 | struct sock *next = l2cap_pi(sk)->next_c, *prev = l2cap_pi(sk)->prev_c; | 170 | struct l2cap_chan *next = chan->next_c, *prev = chan->prev_c; |
158 | 171 | ||
159 | write_lock_bh(&l->lock); | 172 | write_lock_bh(&l->lock); |
160 | if (sk == l->head) | 173 | if (chan == l->head) |
161 | l->head = next; | 174 | l->head = next; |
162 | 175 | ||
163 | if (next) | 176 | if (next) |
164 | l2cap_pi(next)->prev_c = prev; | 177 | next->prev_c = prev; |
165 | if (prev) | 178 | if (prev) |
166 | l2cap_pi(prev)->next_c = next; | 179 | prev->next_c = next; |
167 | write_unlock_bh(&l->lock); | 180 | write_unlock_bh(&l->lock); |
168 | 181 | ||
169 | __sock_put(sk); | 182 | __sock_put(chan->sk); |
170 | } | 183 | } |
171 | 184 | ||
172 | static void __l2cap_chan_add(struct l2cap_conn *conn, struct sock *sk) | 185 | static void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan) |
173 | { | 186 | { |
174 | struct l2cap_chan_list *l = &conn->chan_list; | 187 | struct l2cap_chan_list *l = &conn->chan_list; |
188 | struct sock *sk = chan->sk; | ||
175 | 189 | ||
176 | BT_DBG("conn %p, psm 0x%2.2x, dcid 0x%4.4x", conn, | 190 | BT_DBG("conn %p, psm 0x%2.2x, dcid 0x%4.4x", conn, |
177 | l2cap_pi(sk)->psm, l2cap_pi(sk)->dcid); | 191 | l2cap_pi(sk)->psm, l2cap_pi(sk)->dcid); |
@@ -203,13 +217,14 @@ static void __l2cap_chan_add(struct l2cap_conn *conn, struct sock *sk) | |||
203 | l2cap_pi(sk)->omtu = L2CAP_DEFAULT_MTU; | 217 | l2cap_pi(sk)->omtu = L2CAP_DEFAULT_MTU; |
204 | } | 218 | } |
205 | 219 | ||
206 | __l2cap_chan_link(l, sk); | 220 | __l2cap_chan_link(l, chan); |
207 | } | 221 | } |
208 | 222 | ||
209 | /* Delete channel. | 223 | /* Delete channel. |
210 | * Must be called on the locked socket. */ | 224 | * Must be called on the locked socket. */ |
211 | void l2cap_chan_del(struct sock *sk, int err) | 225 | void l2cap_chan_del(struct l2cap_chan *chan, int err) |
212 | { | 226 | { |
227 | struct sock *sk = chan->sk; | ||
213 | struct l2cap_conn *conn = l2cap_pi(sk)->conn; | 228 | struct l2cap_conn *conn = l2cap_pi(sk)->conn; |
214 | struct sock *parent = bt_sk(sk)->parent; | 229 | struct sock *parent = bt_sk(sk)->parent; |
215 | 230 | ||
@@ -219,7 +234,7 @@ void l2cap_chan_del(struct sock *sk, int err) | |||
219 | 234 | ||
220 | if (conn) { | 235 | if (conn) { |
221 | /* Unlink from channel list */ | 236 | /* Unlink from channel list */ |
222 | l2cap_chan_unlink(&conn->chan_list, sk); | 237 | l2cap_chan_unlink(&conn->chan_list, chan); |
223 | l2cap_pi(sk)->conn = NULL; | 238 | l2cap_pi(sk)->conn = NULL; |
224 | hci_conn_put(conn->hcon); | 239 | hci_conn_put(conn->hcon); |
225 | } | 240 | } |
@@ -253,6 +268,8 @@ void l2cap_chan_del(struct sock *sk, int err) | |||
253 | kfree(l); | 268 | kfree(l); |
254 | } | 269 | } |
255 | } | 270 | } |
271 | |||
272 | kfree(chan); | ||
256 | } | 273 | } |
257 | 274 | ||
258 | static inline u8 l2cap_get_auth_type(struct sock *sk) | 275 | static inline u8 l2cap_get_auth_type(struct sock *sk) |
@@ -487,7 +504,7 @@ static void l2cap_conn_start(struct l2cap_conn *conn) | |||
487 | { | 504 | { |
488 | struct l2cap_chan_list *l = &conn->chan_list; | 505 | struct l2cap_chan_list *l = &conn->chan_list; |
489 | struct sock_del_list del, *tmp1, *tmp2; | 506 | struct sock_del_list del, *tmp1, *tmp2; |
490 | struct sock *sk; | 507 | struct l2cap_chan *chan; |
491 | 508 | ||
492 | BT_DBG("conn %p", conn); | 509 | BT_DBG("conn %p", conn); |
493 | 510 | ||
@@ -495,7 +512,8 @@ static void l2cap_conn_start(struct l2cap_conn *conn) | |||
495 | 512 | ||
496 | read_lock(&l->lock); | 513 | read_lock(&l->lock); |
497 | 514 | ||
498 | for (sk = l->head; sk; sk = l2cap_pi(sk)->next_c) { | 515 | for (chan = l->head; chan; chan = chan->next_c) { |
516 | struct sock *sk = chan->sk; | ||
499 | bh_lock_sock(sk); | 517 | bh_lock_sock(sk); |
500 | 518 | ||
501 | if (sk->sk_type != SOCK_SEQPACKET && | 519 | if (sk->sk_type != SOCK_SEQPACKET && |
@@ -622,6 +640,7 @@ static void l2cap_le_conn_ready(struct l2cap_conn *conn) | |||
622 | { | 640 | { |
623 | struct l2cap_chan_list *list = &conn->chan_list; | 641 | struct l2cap_chan_list *list = &conn->chan_list; |
624 | struct sock *parent, *uninitialized_var(sk); | 642 | struct sock *parent, *uninitialized_var(sk); |
643 | struct l2cap_chan *chan; | ||
625 | 644 | ||
626 | BT_DBG(""); | 645 | BT_DBG(""); |
627 | 646 | ||
@@ -641,6 +660,12 @@ static void l2cap_le_conn_ready(struct l2cap_conn *conn) | |||
641 | if (!sk) | 660 | if (!sk) |
642 | goto clean; | 661 | goto clean; |
643 | 662 | ||
663 | chan = l2cap_chan_alloc(sk); | ||
664 | if (!chan) { | ||
665 | l2cap_sock_kill(sk); | ||
666 | goto clean; | ||
667 | } | ||
668 | |||
644 | write_lock_bh(&list->lock); | 669 | write_lock_bh(&list->lock); |
645 | 670 | ||
646 | hci_conn_hold(conn->hcon); | 671 | hci_conn_hold(conn->hcon); |
@@ -651,7 +676,9 @@ static void l2cap_le_conn_ready(struct l2cap_conn *conn) | |||
651 | 676 | ||
652 | bt_accept_enqueue(parent, sk); | 677 | bt_accept_enqueue(parent, sk); |
653 | 678 | ||
654 | __l2cap_chan_add(conn, sk); | 679 | __l2cap_chan_add(conn, chan); |
680 | |||
681 | l2cap_pi(sk)->chan = chan; | ||
655 | 682 | ||
656 | l2cap_sock_set_timer(sk, sk->sk_sndtimeo); | 683 | l2cap_sock_set_timer(sk, sk->sk_sndtimeo); |
657 | 684 | ||
@@ -667,7 +694,7 @@ clean: | |||
667 | static void l2cap_conn_ready(struct l2cap_conn *conn) | 694 | static void l2cap_conn_ready(struct l2cap_conn *conn) |
668 | { | 695 | { |
669 | struct l2cap_chan_list *l = &conn->chan_list; | 696 | struct l2cap_chan_list *l = &conn->chan_list; |
670 | struct sock *sk; | 697 | struct l2cap_chan *chan; |
671 | 698 | ||
672 | BT_DBG("conn %p", conn); | 699 | BT_DBG("conn %p", conn); |
673 | 700 | ||
@@ -676,7 +703,8 @@ static void l2cap_conn_ready(struct l2cap_conn *conn) | |||
676 | 703 | ||
677 | read_lock(&l->lock); | 704 | read_lock(&l->lock); |
678 | 705 | ||
679 | for (sk = l->head; sk; sk = l2cap_pi(sk)->next_c) { | 706 | for (chan = l->head; chan; chan = chan->next_c) { |
707 | struct sock *sk = chan->sk; | ||
680 | bh_lock_sock(sk); | 708 | bh_lock_sock(sk); |
681 | 709 | ||
682 | if (conn->hcon->type == LE_LINK) { | 710 | if (conn->hcon->type == LE_LINK) { |
@@ -703,13 +731,14 @@ static void l2cap_conn_ready(struct l2cap_conn *conn) | |||
703 | static void l2cap_conn_unreliable(struct l2cap_conn *conn, int err) | 731 | static void l2cap_conn_unreliable(struct l2cap_conn *conn, int err) |
704 | { | 732 | { |
705 | struct l2cap_chan_list *l = &conn->chan_list; | 733 | struct l2cap_chan_list *l = &conn->chan_list; |
706 | struct sock *sk; | 734 | struct l2cap_chan *chan; |
707 | 735 | ||
708 | BT_DBG("conn %p", conn); | 736 | BT_DBG("conn %p", conn); |
709 | 737 | ||
710 | read_lock(&l->lock); | 738 | read_lock(&l->lock); |
711 | 739 | ||
712 | for (sk = l->head; sk; sk = l2cap_pi(sk)->next_c) { | 740 | for (chan = l->head; chan; chan = chan->next_c) { |
741 | struct sock *sk = chan->sk; | ||
713 | if (l2cap_pi(sk)->force_reliable) | 742 | if (l2cap_pi(sk)->force_reliable) |
714 | sk->sk_err = err; | 743 | sk->sk_err = err; |
715 | } | 744 | } |
@@ -768,6 +797,7 @@ static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status) | |||
768 | static void l2cap_conn_del(struct hci_conn *hcon, int err) | 797 | static void l2cap_conn_del(struct hci_conn *hcon, int err) |
769 | { | 798 | { |
770 | struct l2cap_conn *conn = hcon->l2cap_data; | 799 | struct l2cap_conn *conn = hcon->l2cap_data; |
800 | struct l2cap_chan *chan; | ||
771 | struct sock *sk; | 801 | struct sock *sk; |
772 | 802 | ||
773 | if (!conn) | 803 | if (!conn) |
@@ -778,9 +808,10 @@ static void l2cap_conn_del(struct hci_conn *hcon, int err) | |||
778 | kfree_skb(conn->rx_skb); | 808 | kfree_skb(conn->rx_skb); |
779 | 809 | ||
780 | /* Kill channels */ | 810 | /* Kill channels */ |
781 | while ((sk = conn->chan_list.head)) { | 811 | while ((chan = conn->chan_list.head)) { |
812 | sk = chan->sk; | ||
782 | bh_lock_sock(sk); | 813 | bh_lock_sock(sk); |
783 | l2cap_chan_del(sk, err); | 814 | l2cap_chan_del(chan, err); |
784 | bh_unlock_sock(sk); | 815 | bh_unlock_sock(sk); |
785 | l2cap_sock_kill(sk); | 816 | l2cap_sock_kill(sk); |
786 | } | 817 | } |
@@ -792,11 +823,11 @@ static void l2cap_conn_del(struct hci_conn *hcon, int err) | |||
792 | kfree(conn); | 823 | kfree(conn); |
793 | } | 824 | } |
794 | 825 | ||
795 | static inline void l2cap_chan_add(struct l2cap_conn *conn, struct sock *sk) | 826 | static inline void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan) |
796 | { | 827 | { |
797 | struct l2cap_chan_list *l = &conn->chan_list; | 828 | struct l2cap_chan_list *l = &conn->chan_list; |
798 | write_lock_bh(&l->lock); | 829 | write_lock_bh(&l->lock); |
799 | __l2cap_chan_add(conn, sk); | 830 | __l2cap_chan_add(conn, chan); |
800 | write_unlock_bh(&l->lock); | 831 | write_unlock_bh(&l->lock); |
801 | } | 832 | } |
802 | 833 | ||
@@ -837,6 +868,7 @@ int l2cap_do_connect(struct sock *sk) | |||
837 | bdaddr_t *src = &bt_sk(sk)->src; | 868 | bdaddr_t *src = &bt_sk(sk)->src; |
838 | bdaddr_t *dst = &bt_sk(sk)->dst; | 869 | bdaddr_t *dst = &bt_sk(sk)->dst; |
839 | struct l2cap_conn *conn; | 870 | struct l2cap_conn *conn; |
871 | struct l2cap_chan *chan; | ||
840 | struct hci_conn *hcon; | 872 | struct hci_conn *hcon; |
841 | struct hci_dev *hdev; | 873 | struct hci_dev *hdev; |
842 | __u8 auth_type; | 874 | __u8 auth_type; |
@@ -872,10 +904,19 @@ int l2cap_do_connect(struct sock *sk) | |||
872 | goto done; | 904 | goto done; |
873 | } | 905 | } |
874 | 906 | ||
907 | chan = l2cap_chan_alloc(sk); | ||
908 | if (!chan) { | ||
909 | hci_conn_put(hcon); | ||
910 | err = -ENOMEM; | ||
911 | goto done; | ||
912 | } | ||
913 | |||
875 | /* Update source addr of the socket */ | 914 | /* Update source addr of the socket */ |
876 | bacpy(src, conn->src); | 915 | bacpy(src, conn->src); |
877 | 916 | ||
878 | l2cap_chan_add(conn, sk); | 917 | l2cap_chan_add(conn, chan); |
918 | |||
919 | l2cap_pi(sk)->chan = chan; | ||
879 | 920 | ||
880 | sk->sk_state = BT_CONNECT; | 921 | sk->sk_state = BT_CONNECT; |
881 | l2cap_sock_set_timer(sk, sk->sk_sndtimeo); | 922 | l2cap_sock_set_timer(sk, sk->sk_sndtimeo); |
@@ -1387,12 +1428,13 @@ static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb) | |||
1387 | { | 1428 | { |
1388 | struct l2cap_chan_list *l = &conn->chan_list; | 1429 | struct l2cap_chan_list *l = &conn->chan_list; |
1389 | struct sk_buff *nskb; | 1430 | struct sk_buff *nskb; |
1390 | struct sock *sk; | 1431 | struct l2cap_chan *chan; |
1391 | 1432 | ||
1392 | BT_DBG("conn %p", conn); | 1433 | BT_DBG("conn %p", conn); |
1393 | 1434 | ||
1394 | read_lock(&l->lock); | 1435 | read_lock(&l->lock); |
1395 | for (sk = l->head; sk; sk = l2cap_pi(sk)->next_c) { | 1436 | for (chan = l->head; chan; chan = chan->next_c) { |
1437 | struct sock *sk = chan->sk; | ||
1396 | if (sk->sk_type != SOCK_RAW) | 1438 | if (sk->sk_type != SOCK_RAW) |
1397 | continue; | 1439 | continue; |
1398 | 1440 | ||
@@ -1976,6 +2018,7 @@ static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hd | |||
1976 | struct l2cap_chan_list *list = &conn->chan_list; | 2018 | struct l2cap_chan_list *list = &conn->chan_list; |
1977 | struct l2cap_conn_req *req = (struct l2cap_conn_req *) data; | 2019 | struct l2cap_conn_req *req = (struct l2cap_conn_req *) data; |
1978 | struct l2cap_conn_rsp rsp; | 2020 | struct l2cap_conn_rsp rsp; |
2021 | struct l2cap_chan *chan; | ||
1979 | struct sock *parent, *sk = NULL; | 2022 | struct sock *parent, *sk = NULL; |
1980 | int result, status = L2CAP_CS_NO_INFO; | 2023 | int result, status = L2CAP_CS_NO_INFO; |
1981 | 2024 | ||
@@ -2013,6 +2056,12 @@ static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hd | |||
2013 | if (!sk) | 2056 | if (!sk) |
2014 | goto response; | 2057 | goto response; |
2015 | 2058 | ||
2059 | chan = l2cap_chan_alloc(sk); | ||
2060 | if (!chan) { | ||
2061 | l2cap_sock_kill(sk); | ||
2062 | goto response; | ||
2063 | } | ||
2064 | |||
2016 | write_lock_bh(&list->lock); | 2065 | write_lock_bh(&list->lock); |
2017 | 2066 | ||
2018 | /* Check if we already have channel with that dcid */ | 2067 | /* Check if we already have channel with that dcid */ |
@@ -2033,7 +2082,10 @@ static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hd | |||
2033 | 2082 | ||
2034 | bt_accept_enqueue(parent, sk); | 2083 | bt_accept_enqueue(parent, sk); |
2035 | 2084 | ||
2036 | __l2cap_chan_add(conn, sk); | 2085 | __l2cap_chan_add(conn, chan); |
2086 | |||
2087 | l2cap_pi(sk)->chan = chan; | ||
2088 | |||
2037 | dcid = l2cap_pi(sk)->scid; | 2089 | dcid = l2cap_pi(sk)->scid; |
2038 | 2090 | ||
2039 | l2cap_sock_set_timer(sk, sk->sk_sndtimeo); | 2091 | l2cap_sock_set_timer(sk, sk->sk_sndtimeo); |
@@ -2105,6 +2157,7 @@ static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hd | |||
2105 | { | 2157 | { |
2106 | struct l2cap_conn_rsp *rsp = (struct l2cap_conn_rsp *) data; | 2158 | struct l2cap_conn_rsp *rsp = (struct l2cap_conn_rsp *) data; |
2107 | u16 scid, dcid, result, status; | 2159 | u16 scid, dcid, result, status; |
2160 | struct l2cap_chan *chan; | ||
2108 | struct sock *sk; | 2161 | struct sock *sk; |
2109 | u8 req[128]; | 2162 | u8 req[128]; |
2110 | 2163 | ||
@@ -2116,15 +2169,17 @@ static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hd | |||
2116 | BT_DBG("dcid 0x%4.4x scid 0x%4.4x result 0x%2.2x status 0x%2.2x", dcid, scid, result, status); | 2169 | BT_DBG("dcid 0x%4.4x scid 0x%4.4x result 0x%2.2x status 0x%2.2x", dcid, scid, result, status); |
2117 | 2170 | ||
2118 | if (scid) { | 2171 | if (scid) { |
2119 | sk = l2cap_get_chan_by_scid(&conn->chan_list, scid); | 2172 | chan = l2cap_get_chan_by_scid(&conn->chan_list, scid); |
2120 | if (!sk) | 2173 | if (!chan) |
2121 | return -EFAULT; | 2174 | return -EFAULT; |
2122 | } else { | 2175 | } else { |
2123 | sk = l2cap_get_chan_by_ident(&conn->chan_list, cmd->ident); | 2176 | chan = l2cap_get_chan_by_ident(&conn->chan_list, cmd->ident); |
2124 | if (!sk) | 2177 | if (!chan) |
2125 | return -EFAULT; | 2178 | return -EFAULT; |
2126 | } | 2179 | } |
2127 | 2180 | ||
2181 | sk = chan->sk; | ||
2182 | |||
2128 | switch (result) { | 2183 | switch (result) { |
2129 | case L2CAP_CR_SUCCESS: | 2184 | case L2CAP_CR_SUCCESS: |
2130 | sk->sk_state = BT_CONFIG; | 2185 | sk->sk_state = BT_CONFIG; |
@@ -2155,7 +2210,7 @@ static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hd | |||
2155 | break; | 2210 | break; |
2156 | } | 2211 | } |
2157 | 2212 | ||
2158 | l2cap_chan_del(sk, ECONNREFUSED); | 2213 | l2cap_chan_del(chan, ECONNREFUSED); |
2159 | break; | 2214 | break; |
2160 | } | 2215 | } |
2161 | 2216 | ||
@@ -2179,6 +2234,7 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr | |||
2179 | struct l2cap_conf_req *req = (struct l2cap_conf_req *) data; | 2234 | struct l2cap_conf_req *req = (struct l2cap_conf_req *) data; |
2180 | u16 dcid, flags; | 2235 | u16 dcid, flags; |
2181 | u8 rsp[64]; | 2236 | u8 rsp[64]; |
2237 | struct l2cap_chan *chan; | ||
2182 | struct sock *sk; | 2238 | struct sock *sk; |
2183 | int len; | 2239 | int len; |
2184 | 2240 | ||
@@ -2187,10 +2243,12 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr | |||
2187 | 2243 | ||
2188 | BT_DBG("dcid 0x%4.4x flags 0x%2.2x", dcid, flags); | 2244 | BT_DBG("dcid 0x%4.4x flags 0x%2.2x", dcid, flags); |
2189 | 2245 | ||
2190 | sk = l2cap_get_chan_by_scid(&conn->chan_list, dcid); | 2246 | chan = l2cap_get_chan_by_scid(&conn->chan_list, dcid); |
2191 | if (!sk) | 2247 | if (!chan) |
2192 | return -ENOENT; | 2248 | return -ENOENT; |
2193 | 2249 | ||
2250 | sk = chan->sk; | ||
2251 | |||
2194 | if (sk->sk_state != BT_CONFIG) { | 2252 | if (sk->sk_state != BT_CONFIG) { |
2195 | struct l2cap_cmd_rej rej; | 2253 | struct l2cap_cmd_rej rej; |
2196 | 2254 | ||
@@ -2269,6 +2327,7 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr | |||
2269 | { | 2327 | { |
2270 | struct l2cap_conf_rsp *rsp = (struct l2cap_conf_rsp *)data; | 2328 | struct l2cap_conf_rsp *rsp = (struct l2cap_conf_rsp *)data; |
2271 | u16 scid, flags, result; | 2329 | u16 scid, flags, result; |
2330 | struct l2cap_chan *chan; | ||
2272 | struct sock *sk; | 2331 | struct sock *sk; |
2273 | int len = cmd->len - sizeof(*rsp); | 2332 | int len = cmd->len - sizeof(*rsp); |
2274 | 2333 | ||
@@ -2279,10 +2338,12 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr | |||
2279 | BT_DBG("scid 0x%4.4x flags 0x%2.2x result 0x%2.2x", | 2338 | BT_DBG("scid 0x%4.4x flags 0x%2.2x result 0x%2.2x", |
2280 | scid, flags, result); | 2339 | scid, flags, result); |
2281 | 2340 | ||
2282 | sk = l2cap_get_chan_by_scid(&conn->chan_list, scid); | 2341 | chan = l2cap_get_chan_by_scid(&conn->chan_list, scid); |
2283 | if (!sk) | 2342 | if (!chan) |
2284 | return 0; | 2343 | return 0; |
2285 | 2344 | ||
2345 | sk = chan->sk; | ||
2346 | |||
2286 | switch (result) { | 2347 | switch (result) { |
2287 | case L2CAP_CONF_SUCCESS: | 2348 | case L2CAP_CONF_SUCCESS: |
2288 | l2cap_conf_rfc_get(sk, rsp->data, len); | 2349 | l2cap_conf_rfc_get(sk, rsp->data, len); |
@@ -2349,6 +2410,7 @@ static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd | |||
2349 | struct l2cap_disconn_req *req = (struct l2cap_disconn_req *) data; | 2410 | struct l2cap_disconn_req *req = (struct l2cap_disconn_req *) data; |
2350 | struct l2cap_disconn_rsp rsp; | 2411 | struct l2cap_disconn_rsp rsp; |
2351 | u16 dcid, scid; | 2412 | u16 dcid, scid; |
2413 | struct l2cap_chan *chan; | ||
2352 | struct sock *sk; | 2414 | struct sock *sk; |
2353 | 2415 | ||
2354 | scid = __le16_to_cpu(req->scid); | 2416 | scid = __le16_to_cpu(req->scid); |
@@ -2356,10 +2418,12 @@ static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd | |||
2356 | 2418 | ||
2357 | BT_DBG("scid 0x%4.4x dcid 0x%4.4x", scid, dcid); | 2419 | BT_DBG("scid 0x%4.4x dcid 0x%4.4x", scid, dcid); |
2358 | 2420 | ||
2359 | sk = l2cap_get_chan_by_scid(&conn->chan_list, dcid); | 2421 | chan = l2cap_get_chan_by_scid(&conn->chan_list, dcid); |
2360 | if (!sk) | 2422 | if (!chan) |
2361 | return 0; | 2423 | return 0; |
2362 | 2424 | ||
2425 | sk = chan->sk; | ||
2426 | |||
2363 | rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid); | 2427 | rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid); |
2364 | rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid); | 2428 | rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid); |
2365 | l2cap_send_cmd(conn, cmd->ident, L2CAP_DISCONN_RSP, sizeof(rsp), &rsp); | 2429 | l2cap_send_cmd(conn, cmd->ident, L2CAP_DISCONN_RSP, sizeof(rsp), &rsp); |
@@ -2375,7 +2439,7 @@ static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd | |||
2375 | return 0; | 2439 | return 0; |
2376 | } | 2440 | } |
2377 | 2441 | ||
2378 | l2cap_chan_del(sk, ECONNRESET); | 2442 | l2cap_chan_del(chan, ECONNRESET); |
2379 | bh_unlock_sock(sk); | 2443 | bh_unlock_sock(sk); |
2380 | 2444 | ||
2381 | l2cap_sock_kill(sk); | 2445 | l2cap_sock_kill(sk); |
@@ -2386,6 +2450,7 @@ static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd | |||
2386 | { | 2450 | { |
2387 | struct l2cap_disconn_rsp *rsp = (struct l2cap_disconn_rsp *) data; | 2451 | struct l2cap_disconn_rsp *rsp = (struct l2cap_disconn_rsp *) data; |
2388 | u16 dcid, scid; | 2452 | u16 dcid, scid; |
2453 | struct l2cap_chan *chan; | ||
2389 | struct sock *sk; | 2454 | struct sock *sk; |
2390 | 2455 | ||
2391 | scid = __le16_to_cpu(rsp->scid); | 2456 | scid = __le16_to_cpu(rsp->scid); |
@@ -2393,10 +2458,12 @@ static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd | |||
2393 | 2458 | ||
2394 | BT_DBG("dcid 0x%4.4x scid 0x%4.4x", dcid, scid); | 2459 | BT_DBG("dcid 0x%4.4x scid 0x%4.4x", dcid, scid); |
2395 | 2460 | ||
2396 | sk = l2cap_get_chan_by_scid(&conn->chan_list, scid); | 2461 | chan = l2cap_get_chan_by_scid(&conn->chan_list, scid); |
2397 | if (!sk) | 2462 | if (!chan) |
2398 | return 0; | 2463 | return 0; |
2399 | 2464 | ||
2465 | sk = chan->sk; | ||
2466 | |||
2400 | /* don't delete l2cap channel if sk is owned by user */ | 2467 | /* don't delete l2cap channel if sk is owned by user */ |
2401 | if (sock_owned_by_user(sk)) { | 2468 | if (sock_owned_by_user(sk)) { |
2402 | sk->sk_state = BT_DISCONN; | 2469 | sk->sk_state = BT_DISCONN; |
@@ -2406,7 +2473,7 @@ static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd | |||
2406 | return 0; | 2473 | return 0; |
2407 | } | 2474 | } |
2408 | 2475 | ||
2409 | l2cap_chan_del(sk, 0); | 2476 | l2cap_chan_del(chan, 0); |
2410 | bh_unlock_sock(sk); | 2477 | bh_unlock_sock(sk); |
2411 | 2478 | ||
2412 | l2cap_sock_kill(sk); | 2479 | l2cap_sock_kill(sk); |
@@ -3538,18 +3605,20 @@ drop: | |||
3538 | 3605 | ||
3539 | static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk_buff *skb) | 3606 | static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk_buff *skb) |
3540 | { | 3607 | { |
3608 | struct l2cap_chan *chan; | ||
3541 | struct sock *sk; | 3609 | struct sock *sk; |
3542 | struct l2cap_pinfo *pi; | 3610 | struct l2cap_pinfo *pi; |
3543 | u16 control; | 3611 | u16 control; |
3544 | u8 tx_seq; | 3612 | u8 tx_seq; |
3545 | int len; | 3613 | int len; |
3546 | 3614 | ||
3547 | sk = l2cap_get_chan_by_scid(&conn->chan_list, cid); | 3615 | chan = l2cap_get_chan_by_scid(&conn->chan_list, cid); |
3548 | if (!sk) { | 3616 | if (!chan) { |
3549 | BT_DBG("unknown cid 0x%4.4x", cid); | 3617 | BT_DBG("unknown cid 0x%4.4x", cid); |
3550 | goto drop; | 3618 | goto drop; |
3551 | } | 3619 | } |
3552 | 3620 | ||
3621 | sk = chan->sk; | ||
3553 | pi = l2cap_pi(sk); | 3622 | pi = l2cap_pi(sk); |
3554 | 3623 | ||
3555 | BT_DBG("sk %p, len %d", sk, skb->len); | 3624 | BT_DBG("sk %p, len %d", sk, skb->len); |
@@ -3788,7 +3857,7 @@ static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt) | |||
3788 | { | 3857 | { |
3789 | struct l2cap_chan_list *l; | 3858 | struct l2cap_chan_list *l; |
3790 | struct l2cap_conn *conn = hcon->l2cap_data; | 3859 | struct l2cap_conn *conn = hcon->l2cap_data; |
3791 | struct sock *sk; | 3860 | struct l2cap_chan *chan; |
3792 | 3861 | ||
3793 | if (!conn) | 3862 | if (!conn) |
3794 | return 0; | 3863 | return 0; |
@@ -3799,7 +3868,8 @@ static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt) | |||
3799 | 3868 | ||
3800 | read_lock(&l->lock); | 3869 | read_lock(&l->lock); |
3801 | 3870 | ||
3802 | for (sk = l->head; sk; sk = l2cap_pi(sk)->next_c) { | 3871 | for (chan = l->head; chan; chan = chan->next_c) { |
3872 | struct sock *sk = chan->sk; | ||
3803 | bh_lock_sock(sk); | 3873 | bh_lock_sock(sk); |
3804 | 3874 | ||
3805 | if (l2cap_pi(sk)->conf_state & L2CAP_CONF_CONNECT_PEND) { | 3875 | if (l2cap_pi(sk)->conf_state & L2CAP_CONF_CONNECT_PEND) { |
@@ -3872,7 +3942,7 @@ static int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 fl | |||
3872 | 3942 | ||
3873 | if (!(flags & ACL_CONT)) { | 3943 | if (!(flags & ACL_CONT)) { |
3874 | struct l2cap_hdr *hdr; | 3944 | struct l2cap_hdr *hdr; |
3875 | struct sock *sk; | 3945 | struct l2cap_chan *chan; |
3876 | u16 cid; | 3946 | u16 cid; |
3877 | int len; | 3947 | int len; |
3878 | 3948 | ||
@@ -3910,18 +3980,21 @@ static int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 fl | |||
3910 | goto drop; | 3980 | goto drop; |
3911 | } | 3981 | } |
3912 | 3982 | ||
3913 | sk = l2cap_get_chan_by_scid(&conn->chan_list, cid); | 3983 | chan = l2cap_get_chan_by_scid(&conn->chan_list, cid); |
3914 | 3984 | ||
3915 | if (sk && l2cap_pi(sk)->imtu < len - L2CAP_HDR_SIZE) { | 3985 | if (chan && chan->sk) { |
3916 | BT_ERR("Frame exceeding recv MTU (len %d, MTU %d)", | 3986 | struct sock *sk = chan->sk; |
3917 | len, l2cap_pi(sk)->imtu); | ||
3918 | bh_unlock_sock(sk); | ||
3919 | l2cap_conn_unreliable(conn, ECOMM); | ||
3920 | goto drop; | ||
3921 | } | ||
3922 | 3987 | ||
3923 | if (sk) | 3988 | if (l2cap_pi(sk)->imtu < len - L2CAP_HDR_SIZE) { |
3989 | BT_ERR("Frame exceeding recv MTU (len %d, " | ||
3990 | "MTU %d)", len, | ||
3991 | l2cap_pi(sk)->imtu); | ||
3992 | bh_unlock_sock(sk); | ||
3993 | l2cap_conn_unreliable(conn, ECOMM); | ||
3994 | goto drop; | ||
3995 | } | ||
3924 | bh_unlock_sock(sk); | 3996 | bh_unlock_sock(sk); |
3997 | } | ||
3925 | 3998 | ||
3926 | /* Allocate skb for the complete frame (with header) */ | 3999 | /* Allocate skb for the complete frame (with header) */ |
3927 | conn->rx_skb = bt_skb_alloc(len, GFP_ATOMIC); | 4000 | conn->rx_skb = bt_skb_alloc(len, GFP_ATOMIC); |
diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index f77308e63e58..7df81181a119 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c | |||
@@ -902,7 +902,7 @@ void __l2cap_sock_close(struct sock *sk, int reason) | |||
902 | l2cap_sock_set_timer(sk, sk->sk_sndtimeo); | 902 | l2cap_sock_set_timer(sk, sk->sk_sndtimeo); |
903 | l2cap_send_disconn_req(conn, sk, reason); | 903 | l2cap_send_disconn_req(conn, sk, reason); |
904 | } else | 904 | } else |
905 | l2cap_chan_del(sk, reason); | 905 | l2cap_chan_del(l2cap_pi(sk)->chan, reason); |
906 | break; | 906 | break; |
907 | 907 | ||
908 | case BT_CONNECT2: | 908 | case BT_CONNECT2: |
@@ -925,12 +925,12 @@ void __l2cap_sock_close(struct sock *sk, int reason) | |||
925 | L2CAP_CONN_RSP, sizeof(rsp), &rsp); | 925 | L2CAP_CONN_RSP, sizeof(rsp), &rsp); |
926 | } | 926 | } |
927 | 927 | ||
928 | l2cap_chan_del(sk, reason); | 928 | l2cap_chan_del(l2cap_pi(sk)->chan, reason); |
929 | break; | 929 | break; |
930 | 930 | ||
931 | case BT_CONNECT: | 931 | case BT_CONNECT: |
932 | case BT_DISCONN: | 932 | case BT_DISCONN: |
933 | l2cap_chan_del(sk, reason); | 933 | l2cap_chan_del(l2cap_pi(sk)->chan, reason); |
934 | break; | 934 | break; |
935 | 935 | ||
936 | default: | 936 | default: |