Commit | Line | Data |
---|---|---|
bb58f747 GP |
1 | /* |
2 | BlueZ - Bluetooth protocol stack for Linux | |
3 | Copyright (C) 2000-2001 Qualcomm Incorporated | |
4 | Copyright (C) 2009-2010 Gustavo F. Padovan <gustavo@padovan.org> | |
5 | Copyright (C) 2010 Google Inc. | |
6 | ||
7 | Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com> | |
8 | ||
9 | This program is free software; you can redistribute it and/or modify | |
10 | it under the terms of the GNU General Public License version 2 as | |
11 | published by the Free Software Foundation; | |
12 | ||
13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | |
14 | OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. | |
16 | IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY | |
17 | CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES | |
18 | WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | |
19 | ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | |
20 | OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |
21 | ||
22 | ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS, | |
23 | COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS | |
24 | SOFTWARE IS DISCLAIMED. | |
25 | */ | |
26 | ||
27 | /* Bluetooth L2CAP sockets. */ | |
28 | ||
29 | #include <net/bluetooth/bluetooth.h> | |
30 | #include <net/bluetooth/l2cap.h> | |
31 | ||
32 | static void l2cap_sock_timeout(unsigned long arg) | |
33 | { | |
34 | struct sock *sk = (struct sock *) arg; | |
35 | int reason; | |
36 | ||
37 | BT_DBG("sock %p state %d", sk, sk->sk_state); | |
38 | ||
39 | bh_lock_sock(sk); | |
40 | ||
41 | if (sock_owned_by_user(sk)) { | |
42 | /* sk is owned by user. Try again later */ | |
43 | l2cap_sock_set_timer(sk, HZ / 5); | |
44 | bh_unlock_sock(sk); | |
45 | sock_put(sk); | |
46 | return; | |
47 | } | |
48 | ||
49 | if (sk->sk_state == BT_CONNECTED || sk->sk_state == BT_CONFIG) | |
50 | reason = ECONNREFUSED; | |
51 | else if (sk->sk_state == BT_CONNECT && | |
52 | l2cap_pi(sk)->sec_level != BT_SECURITY_SDP) | |
53 | reason = ECONNREFUSED; | |
54 | else | |
55 | reason = ETIMEDOUT; | |
56 | ||
57 | __l2cap_sock_close(sk, reason); | |
58 | ||
59 | bh_unlock_sock(sk); | |
60 | ||
61 | l2cap_sock_kill(sk); | |
62 | sock_put(sk); | |
63 | } | |
64 | ||
554f05bb GP |
65 | static int l2cap_sock_release(struct socket *sock) |
66 | { | |
67 | struct sock *sk = sock->sk; | |
68 | int err; | |
69 | ||
70 | BT_DBG("sock %p, sk %p", sock, sk); | |
71 | ||
72 | if (!sk) | |
73 | return 0; | |
74 | ||
75 | err = l2cap_sock_shutdown(sock, 2); | |
76 | ||
77 | sock_orphan(sk); | |
78 | l2cap_sock_kill(sk); | |
79 | return err; | |
80 | } | |
81 | ||
bb58f747 GP |
82 | static void l2cap_sock_destruct(struct sock *sk) |
83 | { | |
84 | BT_DBG("sk %p", sk); | |
85 | ||
86 | skb_queue_purge(&sk->sk_receive_queue); | |
87 | skb_queue_purge(&sk->sk_write_queue); | |
88 | } | |
89 | ||
90 | void l2cap_sock_init(struct sock *sk, struct sock *parent) | |
91 | { | |
92 | struct l2cap_pinfo *pi = l2cap_pi(sk); | |
93 | ||
94 | BT_DBG("sk %p", sk); | |
95 | ||
96 | if (parent) { | |
97 | sk->sk_type = parent->sk_type; | |
98 | bt_sk(sk)->defer_setup = bt_sk(parent)->defer_setup; | |
99 | ||
100 | pi->imtu = l2cap_pi(parent)->imtu; | |
101 | pi->omtu = l2cap_pi(parent)->omtu; | |
102 | pi->conf_state = l2cap_pi(parent)->conf_state; | |
103 | pi->mode = l2cap_pi(parent)->mode; | |
104 | pi->fcs = l2cap_pi(parent)->fcs; | |
105 | pi->max_tx = l2cap_pi(parent)->max_tx; | |
106 | pi->tx_win = l2cap_pi(parent)->tx_win; | |
107 | pi->sec_level = l2cap_pi(parent)->sec_level; | |
108 | pi->role_switch = l2cap_pi(parent)->role_switch; | |
109 | pi->force_reliable = l2cap_pi(parent)->force_reliable; | |
110 | pi->flushable = l2cap_pi(parent)->flushable; | |
111 | } else { | |
112 | pi->imtu = L2CAP_DEFAULT_MTU; | |
113 | pi->omtu = 0; | |
114 | if (!disable_ertm && sk->sk_type == SOCK_STREAM) { | |
115 | pi->mode = L2CAP_MODE_ERTM; | |
116 | pi->conf_state |= L2CAP_CONF_STATE2_DEVICE; | |
117 | } else { | |
118 | pi->mode = L2CAP_MODE_BASIC; | |
119 | } | |
120 | pi->max_tx = L2CAP_DEFAULT_MAX_TX; | |
121 | pi->fcs = L2CAP_FCS_CRC16; | |
122 | pi->tx_win = L2CAP_DEFAULT_TX_WINDOW; | |
123 | pi->sec_level = BT_SECURITY_LOW; | |
124 | pi->role_switch = 0; | |
125 | pi->force_reliable = 0; | |
126 | pi->flushable = BT_FLUSHABLE_OFF; | |
127 | } | |
128 | ||
129 | /* Default config options */ | |
130 | pi->conf_len = 0; | |
131 | pi->flush_to = L2CAP_DEFAULT_FLUSH_TO; | |
132 | skb_queue_head_init(TX_QUEUE(sk)); | |
133 | skb_queue_head_init(SREJ_QUEUE(sk)); | |
134 | skb_queue_head_init(BUSY_QUEUE(sk)); | |
135 | INIT_LIST_HEAD(SREJ_LIST(sk)); | |
136 | } | |
137 | ||
138 | static struct proto l2cap_proto = { | |
139 | .name = "L2CAP", | |
140 | .owner = THIS_MODULE, | |
141 | .obj_size = sizeof(struct l2cap_pinfo) | |
142 | }; | |
143 | ||
144 | struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock, int proto, gfp_t prio) | |
145 | { | |
146 | struct sock *sk; | |
147 | ||
148 | sk = sk_alloc(net, PF_BLUETOOTH, prio, &l2cap_proto); | |
149 | if (!sk) | |
150 | return NULL; | |
151 | ||
152 | sock_init_data(sock, sk); | |
153 | INIT_LIST_HEAD(&bt_sk(sk)->accept_q); | |
154 | ||
155 | sk->sk_destruct = l2cap_sock_destruct; | |
156 | sk->sk_sndtimeo = msecs_to_jiffies(L2CAP_CONN_TIMEOUT); | |
157 | ||
158 | sock_reset_flag(sk, SOCK_ZAPPED); | |
159 | ||
160 | sk->sk_protocol = proto; | |
161 | sk->sk_state = BT_OPEN; | |
162 | ||
163 | setup_timer(&sk->sk_timer, l2cap_sock_timeout, (unsigned long) sk); | |
164 | ||
165 | bt_sock_link(&l2cap_sk_list, sk); | |
166 | return sk; | |
167 | } | |
168 | ||
169 | static int l2cap_sock_create(struct net *net, struct socket *sock, int protocol, | |
170 | int kern) | |
171 | { | |
172 | struct sock *sk; | |
173 | ||
174 | BT_DBG("sock %p", sock); | |
175 | ||
176 | sock->state = SS_UNCONNECTED; | |
177 | ||
178 | if (sock->type != SOCK_SEQPACKET && sock->type != SOCK_STREAM && | |
179 | sock->type != SOCK_DGRAM && sock->type != SOCK_RAW) | |
180 | return -ESOCKTNOSUPPORT; | |
181 | ||
182 | if (sock->type == SOCK_RAW && !kern && !capable(CAP_NET_RAW)) | |
183 | return -EPERM; | |
184 | ||
185 | sock->ops = &l2cap_sock_ops; | |
186 | ||
187 | sk = l2cap_sock_alloc(net, sock, protocol, GFP_ATOMIC); | |
188 | if (!sk) | |
189 | return -ENOMEM; | |
190 | ||
191 | l2cap_sock_init(sk, NULL); | |
192 | return 0; | |
193 | } | |
194 | ||
65390587 GP |
195 | const struct proto_ops l2cap_sock_ops = { |
196 | .family = PF_BLUETOOTH, | |
197 | .owner = THIS_MODULE, | |
198 | .release = l2cap_sock_release, | |
199 | .bind = l2cap_sock_bind, | |
200 | .connect = l2cap_sock_connect, | |
201 | .listen = l2cap_sock_listen, | |
202 | .accept = l2cap_sock_accept, | |
203 | .getname = l2cap_sock_getname, | |
204 | .sendmsg = l2cap_sock_sendmsg, | |
205 | .recvmsg = l2cap_sock_recvmsg, | |
206 | .poll = bt_sock_poll, | |
207 | .ioctl = bt_sock_ioctl, | |
208 | .mmap = sock_no_mmap, | |
209 | .socketpair = sock_no_socketpair, | |
210 | .shutdown = l2cap_sock_shutdown, | |
211 | .setsockopt = l2cap_sock_setsockopt, | |
212 | .getsockopt = l2cap_sock_getsockopt | |
213 | }; | |
214 | ||
bb58f747 GP |
215 | static const struct net_proto_family l2cap_sock_family_ops = { |
216 | .family = PF_BLUETOOTH, | |
217 | .owner = THIS_MODULE, | |
218 | .create = l2cap_sock_create, | |
219 | }; | |
220 | ||
221 | int __init l2cap_init_sockets(void) | |
222 | { | |
223 | int err; | |
224 | ||
225 | err = proto_register(&l2cap_proto, 0); | |
226 | if (err < 0) | |
227 | return err; | |
228 | ||
229 | err = bt_sock_register(BTPROTO_L2CAP, &l2cap_sock_family_ops); | |
230 | if (err < 0) | |
231 | goto error; | |
232 | ||
233 | BT_INFO("L2CAP socket layer initialized"); | |
234 | ||
235 | return 0; | |
236 | ||
237 | error: | |
238 | BT_ERR("L2CAP socket registration failed"); | |
239 | proto_unregister(&l2cap_proto); | |
240 | return err; | |
241 | } | |
242 | ||
243 | void l2cap_cleanup_sockets(void) | |
244 | { | |
245 | if (bt_sock_unregister(BTPROTO_L2CAP) < 0) | |
246 | BT_ERR("L2CAP socket unregistration failed"); | |
247 | ||
248 | proto_unregister(&l2cap_proto); | |
249 | } |