Blame view

net/bluetooth/l2cap_sock.c 23.1 KB
bb58f747e   Gustavo F. Padovan   Bluetooth: Initia...
1
2
3
4
5
  /*
     BlueZ - Bluetooth protocol stack for Linux
     Copyright (C) 2000-2001 Qualcomm Incorporated
     Copyright (C) 2009-2010 Gustavo F. Padovan <gustavo@padovan.org>
     Copyright (C) 2010 Google Inc.
590051de5   Gustavo F. Padovan   Bluetooth: Add Pr...
6
     Copyright (C) 2011 ProFUSION Embedded Systems
bb58f747e   Gustavo F. Padovan   Bluetooth: Initia...
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
  
     Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com>
  
     This program is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License version 2 as
     published by the Free Software Foundation;
  
     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
     OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
     IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
     CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
     WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
     ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
     OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  
     ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
     COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
     SOFTWARE IS DISCLAIMED.
  */
  
  /* Bluetooth L2CAP sockets. */
6230c9b4f   Paul Moore   bluetooth: Proper...
29
  #include <linux/security.h>
bc3b2d7fb   Paul Gortmaker   net: Add export.h...
30
  #include <linux/export.h>
6230c9b4f   Paul Moore   bluetooth: Proper...
31

bb58f747e   Gustavo F. Padovan   Bluetooth: Initia...
32
  #include <net/bluetooth/bluetooth.h>
33575df7b   Gustavo F. Padovan   Bluetooth: move l...
33
  #include <net/bluetooth/hci_core.h>
bb58f747e   Gustavo F. Padovan   Bluetooth: Initia...
34
  #include <net/bluetooth/l2cap.h>
f1cb9af55   Vinicius Costa Gomes   Bluetooth: Add su...
35
  #include <net/bluetooth/smp.h>
bb58f747e   Gustavo F. Padovan   Bluetooth: Initia...
36

cf2f90f59   Gustavo F. Padovan   Bluetooth: Don't ...
37
  static const struct proto_ops l2cap_sock_ops;
80808e431   Gustavo F. Padovan   Bluetooth: Add l2...
38
39
  static void l2cap_sock_init(struct sock *sk, struct sock *parent);
  static struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock, int proto, gfp_t prio);
cf2f90f59   Gustavo F. Padovan   Bluetooth: Don't ...
40

af6bcd820   Gustavo F. Padovan   Bluetooth: move l...
41
42
43
  static int l2cap_sock_bind(struct socket *sock, struct sockaddr *addr, int alen)
  {
  	struct sock *sk = sock->sk;
4343478f3   Gustavo F. Padovan   Bluetooth: Move s...
44
  	struct l2cap_chan *chan = l2cap_pi(sk)->chan;
af6bcd820   Gustavo F. Padovan   Bluetooth: move l...
45
46
47
48
49
50
51
52
53
54
55
  	struct sockaddr_l2 la;
  	int len, err = 0;
  
  	BT_DBG("sk %p", sk);
  
  	if (!addr || addr->sa_family != AF_BLUETOOTH)
  		return -EINVAL;
  
  	memset(&la, 0, sizeof(la));
  	len = min_t(unsigned int, sizeof(la), alen);
  	memcpy(&la, addr, len);
b62f328b8   Ville Tervo   Bluetooth: Add se...
56
  	if (la.l2_cid && la.l2_psm)
af6bcd820   Gustavo F. Padovan   Bluetooth: move l...
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
  		return -EINVAL;
  
  	lock_sock(sk);
  
  	if (sk->sk_state != BT_OPEN) {
  		err = -EBADFD;
  		goto done;
  	}
  
  	if (la.l2_psm) {
  		__u16 psm = __le16_to_cpu(la.l2_psm);
  
  		/* PSM must be odd and lsb of upper byte must be 0 */
  		if ((psm & 0x0101) != 0x0001) {
  			err = -EINVAL;
  			goto done;
  		}
  
  		/* Restrict usage of well-known PSMs */
  		if (psm < 0x1001 && !capable(CAP_NET_BIND_SERVICE)) {
  			err = -EACCES;
  			goto done;
  		}
  	}
9e4425fff   Gustavo F. Padovan   Bluetooth: Add l2...
81
82
83
84
  	if (la.l2_cid)
  		err = l2cap_add_scid(chan, la.l2_cid);
  	else
  		err = l2cap_add_psm(chan, &la.l2_bdaddr, la.l2_psm);
af6bcd820   Gustavo F. Padovan   Bluetooth: move l...
85

9e4425fff   Gustavo F. Padovan   Bluetooth: Add l2...
86
87
  	if (err < 0)
  		goto done;
af6bcd820   Gustavo F. Padovan   Bluetooth: move l...
88

9e4425fff   Gustavo F. Padovan   Bluetooth: Add l2...
89
90
91
  	if (__le16_to_cpu(la.l2_psm) == 0x0001 ||
  				__le16_to_cpu(la.l2_psm) == 0x0003)
  		chan->sec_level = BT_SECURITY_SDP;
b62f328b8   Ville Tervo   Bluetooth: Add se...
92

9e4425fff   Gustavo F. Padovan   Bluetooth: Add l2...
93
  	bacpy(&bt_sk(sk)->src, &la.l2_bdaddr);
89bc500e4   Gustavo F. Padovan   Bluetooth: Add st...
94
95
  
  	chan->state = BT_BOUND;
9e4425fff   Gustavo F. Padovan   Bluetooth: Add l2...
96
  	sk->sk_state = BT_BOUND;
af6bcd820   Gustavo F. Padovan   Bluetooth: move l...
97
98
99
100
101
  
  done:
  	release_sock(sk);
  	return err;
  }
4e34c50bf   Gustavo F. Padovan   Bluetooth: move l...
102
103
104
  static int l2cap_sock_connect(struct socket *sock, struct sockaddr *addr, int alen, int flags)
  {
  	struct sock *sk = sock->sk;
0c1bc5c62   Gustavo F. Padovan   Bluetooth: Move m...
105
  	struct l2cap_chan *chan = l2cap_pi(sk)->chan;
4e34c50bf   Gustavo F. Padovan   Bluetooth: move l...
106
107
108
109
110
111
112
113
114
115
116
117
  	struct sockaddr_l2 la;
  	int len, err = 0;
  
  	BT_DBG("sk %p", sk);
  
  	if (!addr || alen < sizeof(addr->sa_family) ||
  	    addr->sa_family != AF_BLUETOOTH)
  		return -EINVAL;
  
  	memset(&la, 0, sizeof(la));
  	len = min_t(unsigned int, sizeof(la), alen);
  	memcpy(&la, addr, len);
acd7d3708   Ville Tervo   Bluetooth: Add LE...
118
  	if (la.l2_cid && la.l2_psm)
4e34c50bf   Gustavo F. Padovan   Bluetooth: move l...
119
  		return -EINVAL;
03a001948   Gustavo F. Padovan   Bluetooth: invert...
120
  	err = l2cap_chan_connect(chan, la.l2_psm, la.l2_cid, &la.l2_bdaddr);
4e34c50bf   Gustavo F. Padovan   Bluetooth: move l...
121
122
  	if (err)
  		goto done;
4e34c50bf   Gustavo F. Padovan   Bluetooth: move l...
123
124
125
  	err = bt_sock_wait_state(sk, BT_CONNECTED,
  			sock_sndtimeo(sk, flags & O_NONBLOCK));
  done:
03a001948   Gustavo F. Padovan   Bluetooth: invert...
126
127
  	if (sock_owned_by_user(sk))
  		release_sock(sk);
4e34c50bf   Gustavo F. Padovan   Bluetooth: move l...
128
129
  	return err;
  }
af6bcd820   Gustavo F. Padovan   Bluetooth: move l...
130
131
132
  static int l2cap_sock_listen(struct socket *sock, int backlog)
  {
  	struct sock *sk = sock->sk;
0c1bc5c62   Gustavo F. Padovan   Bluetooth: Move m...
133
  	struct l2cap_chan *chan = l2cap_pi(sk)->chan;
af6bcd820   Gustavo F. Padovan   Bluetooth: move l...
134
135
136
137
138
139
140
141
142
143
144
  	int err = 0;
  
  	BT_DBG("sk %p backlog %d", sk, backlog);
  
  	lock_sock(sk);
  
  	if ((sock->type != SOCK_SEQPACKET && sock->type != SOCK_STREAM)
  			|| sk->sk_state != BT_BOUND) {
  		err = -EBADFD;
  		goto done;
  	}
0c1bc5c62   Gustavo F. Padovan   Bluetooth: Move m...
145
  	switch (chan->mode) {
af6bcd820   Gustavo F. Padovan   Bluetooth: move l...
146
147
148
149
150
151
152
153
154
155
156
  	case L2CAP_MODE_BASIC:
  		break;
  	case L2CAP_MODE_ERTM:
  	case L2CAP_MODE_STREAMING:
  		if (!disable_ertm)
  			break;
  		/* fall through */
  	default:
  		err = -ENOTSUPP;
  		goto done;
  	}
af6bcd820   Gustavo F. Padovan   Bluetooth: move l...
157
158
  	sk->sk_max_ack_backlog = backlog;
  	sk->sk_ack_backlog = 0;
89bc500e4   Gustavo F. Padovan   Bluetooth: Add st...
159
160
  
  	chan->state = BT_LISTEN;
af6bcd820   Gustavo F. Padovan   Bluetooth: move l...
161
162
163
164
165
166
  	sk->sk_state = BT_LISTEN;
  
  done:
  	release_sock(sk);
  	return err;
  }
c47b7c724   Gustavo F. Padovan   Bluetooth: move l...
167
168
169
170
171
172
173
174
  static int l2cap_sock_accept(struct socket *sock, struct socket *newsock, int flags)
  {
  	DECLARE_WAITQUEUE(wait, current);
  	struct sock *sk = sock->sk, *nsk;
  	long timeo;
  	int err = 0;
  
  	lock_sock_nested(sk, SINGLE_DEPTH_NESTING);
c47b7c724   Gustavo F. Padovan   Bluetooth: move l...
175
176
177
178
179
180
  	timeo = sock_rcvtimeo(sk, flags & O_NONBLOCK);
  
  	BT_DBG("sk %p timeo %ld", sk, timeo);
  
  	/* Wait for an incoming connection. (wake-one). */
  	add_wait_queue_exclusive(sk_sleep(sk), &wait);
f9a3c20aa   Peter Hurley   Bluetooth: l2cap:...
181
  	while (1) {
c47b7c724   Gustavo F. Padovan   Bluetooth: move l...
182
  		set_current_state(TASK_INTERRUPTIBLE);
f9a3c20aa   Peter Hurley   Bluetooth: l2cap:...
183
184
185
  
  		if (sk->sk_state != BT_LISTEN) {
  			err = -EBADFD;
c47b7c724   Gustavo F. Padovan   Bluetooth: move l...
186
187
  			break;
  		}
f9a3c20aa   Peter Hurley   Bluetooth: l2cap:...
188
189
190
  		nsk = bt_accept_dequeue(sk, newsock);
  		if (nsk)
  			break;
c47b7c724   Gustavo F. Padovan   Bluetooth: move l...
191

f9a3c20aa   Peter Hurley   Bluetooth: l2cap:...
192
193
  		if (!timeo) {
  			err = -EAGAIN;
c47b7c724   Gustavo F. Padovan   Bluetooth: move l...
194
195
196
197
198
199
200
  			break;
  		}
  
  		if (signal_pending(current)) {
  			err = sock_intr_errno(timeo);
  			break;
  		}
f9a3c20aa   Peter Hurley   Bluetooth: l2cap:...
201
202
203
204
  
  		release_sock(sk);
  		timeo = schedule_timeout(timeo);
  		lock_sock_nested(sk, SINGLE_DEPTH_NESTING);
c47b7c724   Gustavo F. Padovan   Bluetooth: move l...
205
  	}
f9a3c20aa   Peter Hurley   Bluetooth: l2cap:...
206
  	__set_current_state(TASK_RUNNING);
c47b7c724   Gustavo F. Padovan   Bluetooth: move l...
207
208
209
210
211
212
213
214
215
216
217
218
219
  	remove_wait_queue(sk_sleep(sk), &wait);
  
  	if (err)
  		goto done;
  
  	newsock->state = SS_CONNECTED;
  
  	BT_DBG("new socket %p", nsk);
  
  done:
  	release_sock(sk);
  	return err;
  }
d7175d552   Gustavo F. Padovan   Bluetooth: move l...
220
221
222
223
  static int l2cap_sock_getname(struct socket *sock, struct sockaddr *addr, int *len, int peer)
  {
  	struct sockaddr_l2 *la = (struct sockaddr_l2 *) addr;
  	struct sock *sk = sock->sk;
0c1bc5c62   Gustavo F. Padovan   Bluetooth: Move m...
224
  	struct l2cap_chan *chan = l2cap_pi(sk)->chan;
d7175d552   Gustavo F. Padovan   Bluetooth: move l...
225
226
227
228
229
230
231
  
  	BT_DBG("sock %p, sk %p", sock, sk);
  
  	addr->sa_family = AF_BLUETOOTH;
  	*len = sizeof(struct sockaddr_l2);
  
  	if (peer) {
fe4128e0a   Gustavo F. Padovan   Bluetooth: Move m...
232
  		la->l2_psm = chan->psm;
d7175d552   Gustavo F. Padovan   Bluetooth: move l...
233
  		bacpy(&la->l2_bdaddr, &bt_sk(sk)->dst);
fe4128e0a   Gustavo F. Padovan   Bluetooth: Move m...
234
  		la->l2_cid = cpu_to_le16(chan->dcid);
d7175d552   Gustavo F. Padovan   Bluetooth: move l...
235
  	} else {
0c1bc5c62   Gustavo F. Padovan   Bluetooth: Move m...
236
  		la->l2_psm = chan->sport;
d7175d552   Gustavo F. Padovan   Bluetooth: move l...
237
  		bacpy(&la->l2_bdaddr, &bt_sk(sk)->src);
fe4128e0a   Gustavo F. Padovan   Bluetooth: Move m...
238
  		la->l2_cid = cpu_to_le16(chan->scid);
d7175d552   Gustavo F. Padovan   Bluetooth: move l...
239
240
241
242
  	}
  
  	return 0;
  }
99f4808db   Gustavo F. Padovan   Bluetooth: move l...
243
244
245
  static int l2cap_sock_getsockopt_old(struct socket *sock, int optname, char __user *optval, int __user *optlen)
  {
  	struct sock *sk = sock->sk;
4343478f3   Gustavo F. Padovan   Bluetooth: Move s...
246
  	struct l2cap_chan *chan = l2cap_pi(sk)->chan;
99f4808db   Gustavo F. Padovan   Bluetooth: move l...
247
248
249
250
251
252
253
254
255
256
257
258
259
260
  	struct l2cap_options opts;
  	struct l2cap_conninfo cinfo;
  	int len, err = 0;
  	u32 opt;
  
  	BT_DBG("sk %p", sk);
  
  	if (get_user(len, optlen))
  		return -EFAULT;
  
  	lock_sock(sk);
  
  	switch (optname) {
  	case L2CAP_OPTIONS:
e3fb592b1   Vasiliy Kulikov   Bluetooth: l2cap:...
261
  		memset(&opts, 0, sizeof(opts));
0c1bc5c62   Gustavo F. Padovan   Bluetooth: Move m...
262
263
264
265
  		opts.imtu     = chan->imtu;
  		opts.omtu     = chan->omtu;
  		opts.flush_to = chan->flush_to;
  		opts.mode     = chan->mode;
47d1ec616   Gustavo F. Padovan   Bluetooth: Move m...
266
267
  		opts.fcs      = chan->fcs;
  		opts.max_tx   = chan->max_tx;
6327eb980   Andrei Emeltchenko   Bluetooth: EWS: e...
268
  		opts.txwin_size = chan->tx_win;
99f4808db   Gustavo F. Padovan   Bluetooth: move l...
269
270
271
272
273
274
275
276
  
  		len = min_t(unsigned int, len, sizeof(opts));
  		if (copy_to_user(optval, (char *) &opts, len))
  			err = -EFAULT;
  
  		break;
  
  	case L2CAP_LM:
4343478f3   Gustavo F. Padovan   Bluetooth: Move s...
277
  		switch (chan->sec_level) {
99f4808db   Gustavo F. Padovan   Bluetooth: move l...
278
279
280
281
282
283
284
285
286
287
288
289
290
291
  		case BT_SECURITY_LOW:
  			opt = L2CAP_LM_AUTH;
  			break;
  		case BT_SECURITY_MEDIUM:
  			opt = L2CAP_LM_AUTH | L2CAP_LM_ENCRYPT;
  			break;
  		case BT_SECURITY_HIGH:
  			opt = L2CAP_LM_AUTH | L2CAP_LM_ENCRYPT |
  							L2CAP_LM_SECURE;
  			break;
  		default:
  			opt = 0;
  			break;
  		}
43bd0f32d   Andrei Emeltchenko   Bluetooth: conver...
292
  		if (test_bit(FLAG_ROLE_SWITCH, &chan->flags))
99f4808db   Gustavo F. Padovan   Bluetooth: move l...
293
  			opt |= L2CAP_LM_MASTER;
ecf61bdba   Andrei Emeltchenko   Bluetooth: conver...
294
  		if (test_bit(FLAG_FORCE_RELIABLE, &chan->flags))
99f4808db   Gustavo F. Padovan   Bluetooth: move l...
295
296
297
298
299
300
301
302
303
304
305
306
307
  			opt |= L2CAP_LM_RELIABLE;
  
  		if (put_user(opt, (u32 __user *) optval))
  			err = -EFAULT;
  		break;
  
  	case L2CAP_CONNINFO:
  		if (sk->sk_state != BT_CONNECTED &&
  					!(sk->sk_state == BT_CONNECT2 &&
  						bt_sk(sk)->defer_setup)) {
  			err = -ENOTCONN;
  			break;
  		}
8d03e971c   Filip Palian   Bluetooth: l2cap ...
308
  		memset(&cinfo, 0, sizeof(cinfo));
8c1d787be   Gustavo F. Padovan   Bluetooth: Move c...
309
310
  		cinfo.hci_handle = chan->conn->hcon->handle;
  		memcpy(cinfo.dev_class, chan->conn->hcon->dev_class, 3);
99f4808db   Gustavo F. Padovan   Bluetooth: move l...
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
  
  		len = min_t(unsigned int, len, sizeof(cinfo));
  		if (copy_to_user(optval, (char *) &cinfo, len))
  			err = -EFAULT;
  
  		break;
  
  	default:
  		err = -ENOPROTOOPT;
  		break;
  	}
  
  	release_sock(sk);
  	return err;
  }
  
  static int l2cap_sock_getsockopt(struct socket *sock, int level, int optname, char __user *optval, int __user *optlen)
  {
  	struct sock *sk = sock->sk;
4343478f3   Gustavo F. Padovan   Bluetooth: Move s...
330
  	struct l2cap_chan *chan = l2cap_pi(sk)->chan;
99f4808db   Gustavo F. Padovan   Bluetooth: move l...
331
  	struct bt_security sec;
14b12d0b9   Jaikumar Ganesh   Bluetooth: Add BT...
332
  	struct bt_power pwr;
99f4808db   Gustavo F. Padovan   Bluetooth: move l...
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
  	int len, err = 0;
  
  	BT_DBG("sk %p", sk);
  
  	if (level == SOL_L2CAP)
  		return l2cap_sock_getsockopt_old(sock, optname, optval, optlen);
  
  	if (level != SOL_BLUETOOTH)
  		return -ENOPROTOOPT;
  
  	if (get_user(len, optlen))
  		return -EFAULT;
  
  	lock_sock(sk);
  
  	switch (optname) {
  	case BT_SECURITY:
715ec005c   Gustavo F. Padovan   Bluetooth: Add ch...
350
351
  		if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED &&
  					chan->chan_type != L2CAP_CHAN_RAW) {
99f4808db   Gustavo F. Padovan   Bluetooth: move l...
352
353
354
  			err = -EINVAL;
  			break;
  		}
8f3601192   Vinicius Costa Gomes   Bluetooth: Add su...
355
  		memset(&sec, 0, sizeof(sec));
4343478f3   Gustavo F. Padovan   Bluetooth: Move s...
356
  		sec.level = chan->sec_level;
99f4808db   Gustavo F. Padovan   Bluetooth: move l...
357

8f3601192   Vinicius Costa Gomes   Bluetooth: Add su...
358
359
  		if (sk->sk_state == BT_CONNECTED)
  			sec.key_size = chan->conn->hcon->enc_key_size;
99f4808db   Gustavo F. Padovan   Bluetooth: move l...
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
  		len = min_t(unsigned int, len, sizeof(sec));
  		if (copy_to_user(optval, (char *) &sec, len))
  			err = -EFAULT;
  
  		break;
  
  	case BT_DEFER_SETUP:
  		if (sk->sk_state != BT_BOUND && sk->sk_state != BT_LISTEN) {
  			err = -EINVAL;
  			break;
  		}
  
  		if (put_user(bt_sk(sk)->defer_setup, (u32 __user *) optval))
  			err = -EFAULT;
  
  		break;
  
  	case BT_FLUSHABLE:
d57b0e8b8   Andrei Emeltchenko   Bluetooth: conver...
378
379
  		if (put_user(test_bit(FLAG_FLUSHABLE, &chan->flags),
  						(u32 __user *) optval))
99f4808db   Gustavo F. Padovan   Bluetooth: move l...
380
381
382
  			err = -EFAULT;
  
  		break;
14b12d0b9   Jaikumar Ganesh   Bluetooth: Add BT...
383
384
385
386
387
388
  	case BT_POWER:
  		if (sk->sk_type != SOCK_SEQPACKET && sk->sk_type != SOCK_STREAM
  				&& sk->sk_type != SOCK_RAW) {
  			err = -EINVAL;
  			break;
  		}
15770b1ab   Andrei Emeltchenko   Bluetooth: conver...
389
  		pwr.force_active = test_bit(FLAG_FORCE_ACTIVE, &chan->flags);
14b12d0b9   Jaikumar Ganesh   Bluetooth: Add BT...
390
391
392
393
394
395
  
  		len = min_t(unsigned int, len, sizeof(pwr));
  		if (copy_to_user(optval, (char *) &pwr, len))
  			err = -EFAULT;
  
  		break;
2ea664822   Mat Martineau   Bluetooth: Add ch...
396
397
398
399
400
401
402
403
404
  	case BT_CHANNEL_POLICY:
  		if (!enable_hs) {
  			err = -ENOPROTOOPT;
  			break;
  		}
  
  		if (put_user(chan->chan_policy, (u32 __user *) optval))
  			err = -EFAULT;
  		break;
99f4808db   Gustavo F. Padovan   Bluetooth: move l...
405
406
407
408
409
410
411
412
  	default:
  		err = -ENOPROTOOPT;
  		break;
  	}
  
  	release_sock(sk);
  	return err;
  }
33575df7b   Gustavo F. Padovan   Bluetooth: move l...
413
414
415
  static int l2cap_sock_setsockopt_old(struct socket *sock, int optname, char __user *optval, unsigned int optlen)
  {
  	struct sock *sk = sock->sk;
b44500351   Gustavo F. Padovan   Bluetooth: Move c...
416
  	struct l2cap_chan *chan = l2cap_pi(sk)->chan;
33575df7b   Gustavo F. Padovan   Bluetooth: move l...
417
418
419
420
421
422
423
424
425
426
427
428
429
430
  	struct l2cap_options opts;
  	int len, err = 0;
  	u32 opt;
  
  	BT_DBG("sk %p", sk);
  
  	lock_sock(sk);
  
  	switch (optname) {
  	case L2CAP_OPTIONS:
  		if (sk->sk_state == BT_CONNECTED) {
  			err = -EINVAL;
  			break;
  		}
0c1bc5c62   Gustavo F. Padovan   Bluetooth: Move m...
431
432
433
434
  		opts.imtu     = chan->imtu;
  		opts.omtu     = chan->omtu;
  		opts.flush_to = chan->flush_to;
  		opts.mode     = chan->mode;
47d1ec616   Gustavo F. Padovan   Bluetooth: Move m...
435
436
  		opts.fcs      = chan->fcs;
  		opts.max_tx   = chan->max_tx;
6327eb980   Andrei Emeltchenko   Bluetooth: EWS: e...
437
  		opts.txwin_size = chan->tx_win;
33575df7b   Gustavo F. Padovan   Bluetooth: move l...
438
439
440
441
442
443
  
  		len = min_t(unsigned int, sizeof(opts), optlen);
  		if (copy_from_user((char *) &opts, optval, len)) {
  			err = -EFAULT;
  			break;
  		}
6327eb980   Andrei Emeltchenko   Bluetooth: EWS: e...
444
  		if (opts.txwin_size > L2CAP_DEFAULT_EXT_WINDOW) {
33575df7b   Gustavo F. Padovan   Bluetooth: move l...
445
446
447
  			err = -EINVAL;
  			break;
  		}
0c1bc5c62   Gustavo F. Padovan   Bluetooth: Move m...
448
449
  		chan->mode = opts.mode;
  		switch (chan->mode) {
33575df7b   Gustavo F. Padovan   Bluetooth: move l...
450
  		case L2CAP_MODE_BASIC:
c1360a1cf   Gustavo F. Padovan   Bluetooth: use bi...
451
  			clear_bit(CONF_STATE2_DEVICE, &chan->conf_state);
33575df7b   Gustavo F. Padovan   Bluetooth: move l...
452
453
454
455
456
457
458
459
460
461
  			break;
  		case L2CAP_MODE_ERTM:
  		case L2CAP_MODE_STREAMING:
  			if (!disable_ertm)
  				break;
  			/* fall through */
  		default:
  			err = -EINVAL;
  			break;
  		}
0c1bc5c62   Gustavo F. Padovan   Bluetooth: Move m...
462
463
  		chan->imtu = opts.imtu;
  		chan->omtu = opts.omtu;
47d1ec616   Gustavo F. Padovan   Bluetooth: Move m...
464
465
  		chan->fcs  = opts.fcs;
  		chan->max_tx = opts.max_tx;
6327eb980   Andrei Emeltchenko   Bluetooth: EWS: e...
466
  		chan->tx_win = opts.txwin_size;
33575df7b   Gustavo F. Padovan   Bluetooth: move l...
467
468
469
470
471
472
473
474
475
  		break;
  
  	case L2CAP_LM:
  		if (get_user(opt, (u32 __user *) optval)) {
  			err = -EFAULT;
  			break;
  		}
  
  		if (opt & L2CAP_LM_AUTH)
4343478f3   Gustavo F. Padovan   Bluetooth: Move s...
476
  			chan->sec_level = BT_SECURITY_LOW;
33575df7b   Gustavo F. Padovan   Bluetooth: move l...
477
  		if (opt & L2CAP_LM_ENCRYPT)
4343478f3   Gustavo F. Padovan   Bluetooth: Move s...
478
  			chan->sec_level = BT_SECURITY_MEDIUM;
33575df7b   Gustavo F. Padovan   Bluetooth: move l...
479
  		if (opt & L2CAP_LM_SECURE)
4343478f3   Gustavo F. Padovan   Bluetooth: Move s...
480
  			chan->sec_level = BT_SECURITY_HIGH;
33575df7b   Gustavo F. Padovan   Bluetooth: move l...
481

43bd0f32d   Andrei Emeltchenko   Bluetooth: conver...
482
483
484
485
  		if (opt & L2CAP_LM_MASTER)
  			set_bit(FLAG_ROLE_SWITCH, &chan->flags);
  		else
  			clear_bit(FLAG_ROLE_SWITCH, &chan->flags);
ecf61bdba   Andrei Emeltchenko   Bluetooth: conver...
486
487
488
489
490
  
  		if (opt & L2CAP_LM_RELIABLE)
  			set_bit(FLAG_FORCE_RELIABLE, &chan->flags);
  		else
  			clear_bit(FLAG_FORCE_RELIABLE, &chan->flags);
33575df7b   Gustavo F. Padovan   Bluetooth: move l...
491
492
493
494
495
496
497
498
499
500
501
502
503
504
  		break;
  
  	default:
  		err = -ENOPROTOOPT;
  		break;
  	}
  
  	release_sock(sk);
  	return err;
  }
  
  static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, char __user *optval, unsigned int optlen)
  {
  	struct sock *sk = sock->sk;
4343478f3   Gustavo F. Padovan   Bluetooth: Move s...
505
  	struct l2cap_chan *chan = l2cap_pi(sk)->chan;
33575df7b   Gustavo F. Padovan   Bluetooth: move l...
506
  	struct bt_security sec;
14b12d0b9   Jaikumar Ganesh   Bluetooth: Add BT...
507
  	struct bt_power pwr;
f1cb9af55   Vinicius Costa Gomes   Bluetooth: Add su...
508
  	struct l2cap_conn *conn;
33575df7b   Gustavo F. Padovan   Bluetooth: move l...
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
  	int len, err = 0;
  	u32 opt;
  
  	BT_DBG("sk %p", sk);
  
  	if (level == SOL_L2CAP)
  		return l2cap_sock_setsockopt_old(sock, optname, optval, optlen);
  
  	if (level != SOL_BLUETOOTH)
  		return -ENOPROTOOPT;
  
  	lock_sock(sk);
  
  	switch (optname) {
  	case BT_SECURITY:
715ec005c   Gustavo F. Padovan   Bluetooth: Add ch...
524
525
  		if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED &&
  					chan->chan_type != L2CAP_CHAN_RAW) {
33575df7b   Gustavo F. Padovan   Bluetooth: move l...
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
  			err = -EINVAL;
  			break;
  		}
  
  		sec.level = BT_SECURITY_LOW;
  
  		len = min_t(unsigned int, sizeof(sec), optlen);
  		if (copy_from_user((char *) &sec, optval, len)) {
  			err = -EFAULT;
  			break;
  		}
  
  		if (sec.level < BT_SECURITY_LOW ||
  					sec.level > BT_SECURITY_HIGH) {
  			err = -EINVAL;
  			break;
  		}
4343478f3   Gustavo F. Padovan   Bluetooth: Move s...
543
  		chan->sec_level = sec.level;
f1cb9af55   Vinicius Costa Gomes   Bluetooth: Add su...
544

0bee1d60c   Gustavo F. Padovan   Bluetooth: Allow ...
545
546
  		if (!chan->conn)
  			break;
f1cb9af55   Vinicius Costa Gomes   Bluetooth: Add su...
547
  		conn = chan->conn;
0bee1d60c   Gustavo F. Padovan   Bluetooth: Allow ...
548
549
550
  
  		/*change security for LE channels */
  		if (chan->scid == L2CAP_CID_LE_DATA) {
f1cb9af55   Vinicius Costa Gomes   Bluetooth: Add su...
551
552
553
554
555
556
557
  			if (!conn->hcon->out) {
  				err = -EINVAL;
  				break;
  			}
  
  			if (smp_conn_security(conn, sec.level))
  				break;
f1cb9af55   Vinicius Costa Gomes   Bluetooth: Add su...
558
  			sk->sk_state = BT_CONFIG;
3542b854b   Gustavo F. Padovan   Bluetooth: Keep c...
559
  			chan->state = BT_CONFIG;
0bee1d60c   Gustavo F. Padovan   Bluetooth: Allow ...
560
561
562
563
564
565
566
  
  		/* or for ACL link, under defer_setup time */
  		} else if (sk->sk_state == BT_CONNECT2 &&
  					bt_sk(sk)->defer_setup) {
  			err = l2cap_chan_check_security(chan);
  		} else {
  			err = -EINVAL;
f1cb9af55   Vinicius Costa Gomes   Bluetooth: Add su...
567
  		}
33575df7b   Gustavo F. Padovan   Bluetooth: move l...
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
  		break;
  
  	case BT_DEFER_SETUP:
  		if (sk->sk_state != BT_BOUND && sk->sk_state != BT_LISTEN) {
  			err = -EINVAL;
  			break;
  		}
  
  		if (get_user(opt, (u32 __user *) optval)) {
  			err = -EFAULT;
  			break;
  		}
  
  		bt_sk(sk)->defer_setup = opt;
  		break;
  
  	case BT_FLUSHABLE:
  		if (get_user(opt, (u32 __user *) optval)) {
  			err = -EFAULT;
  			break;
  		}
  
  		if (opt > BT_FLUSHABLE_ON) {
  			err = -EINVAL;
  			break;
  		}
  
  		if (opt == BT_FLUSHABLE_OFF) {
8c1d787be   Gustavo F. Padovan   Bluetooth: Move c...
596
  			struct l2cap_conn *conn = chan->conn;
25985edce   Lucas De Marchi   Fix common misspe...
597
  			/* proceed further only when we have l2cap_conn and
33575df7b   Gustavo F. Padovan   Bluetooth: move l...
598
599
600
601
602
603
  			   No Flush support in the LM */
  			if (!conn || !lmp_no_flush_capable(conn->hcon->hdev)) {
  				err = -EINVAL;
  				break;
  			}
  		}
d57b0e8b8   Andrei Emeltchenko   Bluetooth: conver...
604
605
606
607
  		if (opt)
  			set_bit(FLAG_FLUSHABLE, &chan->flags);
  		else
  			clear_bit(FLAG_FLUSHABLE, &chan->flags);
33575df7b   Gustavo F. Padovan   Bluetooth: move l...
608
  		break;
14b12d0b9   Jaikumar Ganesh   Bluetooth: Add BT...
609
610
611
612
613
614
615
616
617
618
619
620
621
622
  	case BT_POWER:
  		if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED &&
  					chan->chan_type != L2CAP_CHAN_RAW) {
  			err = -EINVAL;
  			break;
  		}
  
  		pwr.force_active = BT_POWER_FORCE_ACTIVE_ON;
  
  		len = min_t(unsigned int, sizeof(pwr), optlen);
  		if (copy_from_user((char *) &pwr, optval, len)) {
  			err = -EFAULT;
  			break;
  		}
15770b1ab   Andrei Emeltchenko   Bluetooth: conver...
623
624
625
626
627
  
  		if (pwr.force_active)
  			set_bit(FLAG_FORCE_ACTIVE, &chan->flags);
  		else
  			clear_bit(FLAG_FORCE_ACTIVE, &chan->flags);
14b12d0b9   Jaikumar Ganesh   Bluetooth: Add BT...
628
  		break;
2ea664822   Mat Martineau   Bluetooth: Add ch...
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
  	case BT_CHANNEL_POLICY:
  		if (!enable_hs) {
  			err = -ENOPROTOOPT;
  			break;
  		}
  
  		if (get_user(opt, (u32 __user *) optval)) {
  			err = -EFAULT;
  			break;
  		}
  
  		if (opt > BT_CHANNEL_POLICY_AMP_PREFERRED) {
  			err = -EINVAL;
  			break;
  		}
  
  		if (chan->mode != L2CAP_MODE_ERTM &&
  				chan->mode != L2CAP_MODE_STREAMING) {
  			err = -EOPNOTSUPP;
  			break;
  		}
  
  		chan->chan_policy = (u8) opt;
14b12d0b9   Jaikumar Ganesh   Bluetooth: Add BT...
652
  		break;
33575df7b   Gustavo F. Padovan   Bluetooth: move l...
653
654
655
656
657
658
659
660
  	default:
  		err = -ENOPROTOOPT;
  		break;
  	}
  
  	release_sock(sk);
  	return err;
  }
fd83ccdb3   Gustavo F. Padovan   Bluetooth: move l...
661
662
663
664
  
  static int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, size_t len)
  {
  	struct sock *sk = sock->sk;
0c1bc5c62   Gustavo F. Padovan   Bluetooth: Move m...
665
  	struct l2cap_chan *chan = l2cap_pi(sk)->chan;
fd83ccdb3   Gustavo F. Padovan   Bluetooth: move l...
666
667
668
669
670
671
672
673
674
675
676
677
678
679
  	int err;
  
  	BT_DBG("sock %p, sk %p", sock, sk);
  
  	err = sock_error(sk);
  	if (err)
  		return err;
  
  	if (msg->msg_flags & MSG_OOB)
  		return -EOPNOTSUPP;
  
  	lock_sock(sk);
  
  	if (sk->sk_state != BT_CONNECTED) {
9a91a04a9   Gustavo F. Padovan   Bluetooth: Create...
680
681
  		release_sock(sk);
  		return -ENOTCONN;
fd83ccdb3   Gustavo F. Padovan   Bluetooth: move l...
682
  	}
5e59b791c   Luiz Augusto von Dentz   Bluetooth: set sk...
683
  	err = l2cap_chan_send(chan, msg, len, sk->sk_priority);
fd83ccdb3   Gustavo F. Padovan   Bluetooth: move l...
684

fd83ccdb3   Gustavo F. Padovan   Bluetooth: move l...
685
686
687
  	release_sock(sk);
  	return err;
  }
33575df7b   Gustavo F. Padovan   Bluetooth: move l...
688

689832592   Gustavo F. Padovan   Bluetooth: move l...
689
690
691
  static int l2cap_sock_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, size_t len, int flags)
  {
  	struct sock *sk = sock->sk;
e328140fd   Mat Martineau   Bluetooth: Use ev...
692
693
  	struct l2cap_pinfo *pi = l2cap_pi(sk);
  	int err;
689832592   Gustavo F. Padovan   Bluetooth: move l...
694
695
696
697
  
  	lock_sock(sk);
  
  	if (sk->sk_state == BT_CONNECT2 && bt_sk(sk)->defer_setup) {
8c1d787be   Gustavo F. Padovan   Bluetooth: Move c...
698
  		sk->sk_state = BT_CONFIG;
3542b854b   Gustavo F. Padovan   Bluetooth: Keep c...
699
  		pi->chan->state = BT_CONFIG;
8c1d787be   Gustavo F. Padovan   Bluetooth: Move c...
700

e328140fd   Mat Martineau   Bluetooth: Use ev...
701
  		__l2cap_connect_rsp_defer(pi->chan);
689832592   Gustavo F. Padovan   Bluetooth: move l...
702
703
704
705
706
707
708
  		release_sock(sk);
  		return 0;
  	}
  
  	release_sock(sk);
  
  	if (sock->type == SOCK_STREAM)
e328140fd   Mat Martineau   Bluetooth: Use ev...
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
  		err = bt_sock_stream_recvmsg(iocb, sock, msg, len, flags);
  	else
  		err = bt_sock_recvmsg(iocb, sock, msg, len, flags);
  
  	if (pi->chan->mode != L2CAP_MODE_ERTM)
  		return err;
  
  	/* Attempt to put pending rx data in the socket buffer */
  
  	lock_sock(sk);
  
  	if (!test_bit(CONN_LOCAL_BUSY, &pi->chan->conn_state))
  		goto done;
  
  	if (pi->rx_busy_skb) {
  		if (!sock_queue_rcv_skb(sk, pi->rx_busy_skb))
  			pi->rx_busy_skb = NULL;
  		else
  			goto done;
  	}
  
  	/* Restore data flow when half of the receive buffer is
  	 * available.  This avoids resending large numbers of
  	 * frames.
  	 */
  	if (atomic_read(&sk->sk_rmem_alloc) <= sk->sk_rcvbuf >> 1)
  		l2cap_chan_busy(pi->chan, 0);
689832592   Gustavo F. Padovan   Bluetooth: move l...
736

e328140fd   Mat Martineau   Bluetooth: Use ev...
737
738
739
  done:
  	release_sock(sk);
  	return err;
689832592   Gustavo F. Padovan   Bluetooth: move l...
740
  }
05fc1576d   Gustavo F. Padovan   Bluetooth: move l...
741
742
743
  /* Kill socket (only if zapped and orphan)
   * Must be called on unlocked socket.
   */
ba3bd0ee3   Gustavo F. Padovan   Bluetooth: add cl...
744
  static void l2cap_sock_kill(struct sock *sk)
05fc1576d   Gustavo F. Padovan   Bluetooth: move l...
745
746
747
748
749
750
751
  {
  	if (!sock_flag(sk, SOCK_ZAPPED) || sk->sk_socket)
  		return;
  
  	BT_DBG("sk %p state %d", sk, sk->sk_state);
  
  	/* Kill poor orphan */
6ff5abbf4   Gustavo F. Padovan   Bluetooth: Fix me...
752

23691d75c   Gustavo F. Padovan   Bluetooth: Remove...
753
  	l2cap_chan_destroy(l2cap_pi(sk)->chan);
05fc1576d   Gustavo F. Padovan   Bluetooth: move l...
754
755
756
  	sock_set_flag(sk, SOCK_DEAD);
  	sock_put(sk);
  }
dcba0dba5   Gustavo F. Padovan   Bluetooth: move l...
757
758
759
  static int l2cap_sock_shutdown(struct socket *sock, int how)
  {
  	struct sock *sk = sock->sk;
0c1bc5c62   Gustavo F. Padovan   Bluetooth: Move m...
760
  	struct l2cap_chan *chan = l2cap_pi(sk)->chan;
dcba0dba5   Gustavo F. Padovan   Bluetooth: move l...
761
762
763
764
765
766
767
768
769
  	int err = 0;
  
  	BT_DBG("sock %p, sk %p", sock, sk);
  
  	if (!sk)
  		return 0;
  
  	lock_sock(sk);
  	if (!sk->sk_shutdown) {
0c1bc5c62   Gustavo F. Padovan   Bluetooth: Move m...
770
  		if (chan->mode == L2CAP_MODE_ERTM)
dcba0dba5   Gustavo F. Padovan   Bluetooth: move l...
771
772
773
  			err = __l2cap_wait_ack(sk);
  
  		sk->sk_shutdown = SHUTDOWN_MASK;
0f8527249   Gustavo F. Padovan   Bluetooth: Rename...
774
  		l2cap_chan_close(chan, 0);
dcba0dba5   Gustavo F. Padovan   Bluetooth: move l...
775
776
777
778
779
780
781
782
783
784
785
786
  
  		if (sock_flag(sk, SOCK_LINGER) && sk->sk_lingertime)
  			err = bt_sock_wait_state(sk, BT_CLOSED,
  							sk->sk_lingertime);
  	}
  
  	if (!err && sk->sk_err)
  		err = -sk->sk_err;
  
  	release_sock(sk);
  	return err;
  }
554f05bb8   Gustavo F. Padovan   Bluetooth: move l...
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
  static int l2cap_sock_release(struct socket *sock)
  {
  	struct sock *sk = sock->sk;
  	int err;
  
  	BT_DBG("sock %p, sk %p", sock, sk);
  
  	if (!sk)
  		return 0;
  
  	err = l2cap_sock_shutdown(sock, 2);
  
  	sock_orphan(sk);
  	l2cap_sock_kill(sk);
  	return err;
  }
80808e431   Gustavo F. Padovan   Bluetooth: Add l2...
803
804
805
806
807
808
809
810
811
812
813
814
815
  static struct l2cap_chan *l2cap_sock_new_connection_cb(void *data)
  {
  	struct sock *sk, *parent = data;
  
  	sk = l2cap_sock_alloc(sock_net(parent), NULL, BTPROTO_L2CAP,
  								GFP_ATOMIC);
  	if (!sk)
  		return NULL;
  
  	l2cap_sock_init(sk, parent);
  
  	return l2cap_pi(sk)->chan;
  }
230704942   Gustavo F. Padovan   Bluetooth: add re...
816
817
  static int l2cap_sock_recv_cb(void *data, struct sk_buff *skb)
  {
e328140fd   Mat Martineau   Bluetooth: Use ev...
818
  	int err;
230704942   Gustavo F. Padovan   Bluetooth: add re...
819
  	struct sock *sk = data;
e328140fd   Mat Martineau   Bluetooth: Use ev...
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
  	struct l2cap_pinfo *pi = l2cap_pi(sk);
  
  	if (pi->rx_busy_skb)
  		return -ENOMEM;
  
  	err = sock_queue_rcv_skb(sk, skb);
  
  	/* For ERTM, handle one skb that doesn't fit into the recv
  	 * buffer.  This is important to do because the data frames
  	 * have already been acked, so the skb cannot be discarded.
  	 *
  	 * Notify the l2cap core that the buffer is full, so the
  	 * LOCAL_BUSY state is entered and no more frames are
  	 * acked and reassembled until there is buffer space
  	 * available.
  	 */
  	if (err < 0 && pi->chan->mode == L2CAP_MODE_ERTM) {
  		pi->rx_busy_skb = skb;
  		l2cap_chan_busy(pi->chan, 1);
  		err = 0;
  	}
230704942   Gustavo F. Padovan   Bluetooth: add re...
841

e328140fd   Mat Martineau   Bluetooth: Use ev...
842
  	return err;
230704942   Gustavo F. Padovan   Bluetooth: add re...
843
  }
ba3bd0ee3   Gustavo F. Padovan   Bluetooth: add cl...
844
845
846
847
848
849
  static void l2cap_sock_close_cb(void *data)
  {
  	struct sock *sk = data;
  
  	l2cap_sock_kill(sk);
  }
89bc500e4   Gustavo F. Padovan   Bluetooth: Add st...
850
851
852
853
854
855
  static void l2cap_sock_state_change_cb(void *data, int state)
  {
  	struct sock *sk = data;
  
  	sk->sk_state = state;
  }
80808e431   Gustavo F. Padovan   Bluetooth: Add l2...
856
857
858
  static struct l2cap_ops l2cap_chan_ops = {
  	.name		= "L2CAP Socket Interface",
  	.new_connection	= l2cap_sock_new_connection_cb,
230704942   Gustavo F. Padovan   Bluetooth: add re...
859
  	.recv		= l2cap_sock_recv_cb,
ba3bd0ee3   Gustavo F. Padovan   Bluetooth: add cl...
860
  	.close		= l2cap_sock_close_cb,
89bc500e4   Gustavo F. Padovan   Bluetooth: Add st...
861
  	.state_change	= l2cap_sock_state_change_cb,
80808e431   Gustavo F. Padovan   Bluetooth: Add l2...
862
  };
bb58f747e   Gustavo F. Padovan   Bluetooth: Initia...
863
864
865
  static void l2cap_sock_destruct(struct sock *sk)
  {
  	BT_DBG("sk %p", sk);
e328140fd   Mat Martineau   Bluetooth: Use ev...
866
867
868
869
  	if (l2cap_pi(sk)->rx_busy_skb) {
  		kfree_skb(l2cap_pi(sk)->rx_busy_skb);
  		l2cap_pi(sk)->rx_busy_skb = NULL;
  	}
bb58f747e   Gustavo F. Padovan   Bluetooth: Initia...
870
871
872
  	skb_queue_purge(&sk->sk_receive_queue);
  	skb_queue_purge(&sk->sk_write_queue);
  }
80808e431   Gustavo F. Padovan   Bluetooth: Add l2...
873
  static void l2cap_sock_init(struct sock *sk, struct sock *parent)
bb58f747e   Gustavo F. Padovan   Bluetooth: Initia...
874
875
  {
  	struct l2cap_pinfo *pi = l2cap_pi(sk);
b44500351   Gustavo F. Padovan   Bluetooth: Move c...
876
  	struct l2cap_chan *chan = pi->chan;
bb58f747e   Gustavo F. Padovan   Bluetooth: Initia...
877
878
879
880
  
  	BT_DBG("sk %p", sk);
  
  	if (parent) {
b44500351   Gustavo F. Padovan   Bluetooth: Move c...
881
  		struct l2cap_chan *pchan = l2cap_pi(parent)->chan;
bb58f747e   Gustavo F. Padovan   Bluetooth: Initia...
882
883
  		sk->sk_type = parent->sk_type;
  		bt_sk(sk)->defer_setup = bt_sk(parent)->defer_setup;
715ec005c   Gustavo F. Padovan   Bluetooth: Add ch...
884
  		chan->chan_type = pchan->chan_type;
0c1bc5c62   Gustavo F. Padovan   Bluetooth: Move m...
885
886
  		chan->imtu = pchan->imtu;
  		chan->omtu = pchan->omtu;
b44500351   Gustavo F. Padovan   Bluetooth: Move c...
887
  		chan->conf_state = pchan->conf_state;
0c1bc5c62   Gustavo F. Padovan   Bluetooth: Move m...
888
  		chan->mode = pchan->mode;
47d1ec616   Gustavo F. Padovan   Bluetooth: Move m...
889
890
891
  		chan->fcs  = pchan->fcs;
  		chan->max_tx = pchan->max_tx;
  		chan->tx_win = pchan->tx_win;
6b3c71046   Andrei Emeltchenko   Bluetooth: Initia...
892
  		chan->tx_win_max = pchan->tx_win_max;
4343478f3   Gustavo F. Padovan   Bluetooth: Move s...
893
  		chan->sec_level = pchan->sec_level;
d57b0e8b8   Andrei Emeltchenko   Bluetooth: conver...
894
  		chan->flags = pchan->flags;
6230c9b4f   Paul Moore   bluetooth: Proper...
895
896
  
  		security_sk_clone(parent, sk);
bb58f747e   Gustavo F. Padovan   Bluetooth: Initia...
897
  	} else {
715ec005c   Gustavo F. Padovan   Bluetooth: Add ch...
898
899
900
901
902
903
904
905
906
907
908
909
910
  
  		switch (sk->sk_type) {
  		case SOCK_RAW:
  			chan->chan_type = L2CAP_CHAN_RAW;
  			break;
  		case SOCK_DGRAM:
  			chan->chan_type = L2CAP_CHAN_CONN_LESS;
  			break;
  		case SOCK_SEQPACKET:
  		case SOCK_STREAM:
  			chan->chan_type = L2CAP_CHAN_CONN_ORIENTED;
  			break;
  		}
0c1bc5c62   Gustavo F. Padovan   Bluetooth: Move m...
911
912
  		chan->imtu = L2CAP_DEFAULT_MTU;
  		chan->omtu = 0;
bb58f747e   Gustavo F. Padovan   Bluetooth: Initia...
913
  		if (!disable_ertm && sk->sk_type == SOCK_STREAM) {
0c1bc5c62   Gustavo F. Padovan   Bluetooth: Move m...
914
  			chan->mode = L2CAP_MODE_ERTM;
c1360a1cf   Gustavo F. Padovan   Bluetooth: use bi...
915
  			set_bit(CONF_STATE2_DEVICE, &chan->conf_state);
bb58f747e   Gustavo F. Padovan   Bluetooth: Initia...
916
  		} else {
0c1bc5c62   Gustavo F. Padovan   Bluetooth: Move m...
917
  			chan->mode = L2CAP_MODE_BASIC;
bb58f747e   Gustavo F. Padovan   Bluetooth: Initia...
918
  		}
47d1ec616   Gustavo F. Padovan   Bluetooth: Move m...
919
920
921
  		chan->max_tx = L2CAP_DEFAULT_MAX_TX;
  		chan->fcs  = L2CAP_FCS_CRC16;
  		chan->tx_win = L2CAP_DEFAULT_TX_WINDOW;
6b3c71046   Andrei Emeltchenko   Bluetooth: Initia...
922
  		chan->tx_win_max = L2CAP_DEFAULT_TX_WINDOW;
4343478f3   Gustavo F. Padovan   Bluetooth: Move s...
923
  		chan->sec_level = BT_SECURITY_LOW;
d57b0e8b8   Andrei Emeltchenko   Bluetooth: conver...
924
  		chan->flags = 0;
15770b1ab   Andrei Emeltchenko   Bluetooth: conver...
925
  		set_bit(FLAG_FORCE_ACTIVE, &chan->flags);
bb58f747e   Gustavo F. Padovan   Bluetooth: Initia...
926
927
928
  	}
  
  	/* Default config options */
0c1bc5c62   Gustavo F. Padovan   Bluetooth: Move m...
929
  	chan->flush_to = L2CAP_DEFAULT_FLUSH_TO;
80808e431   Gustavo F. Padovan   Bluetooth: Add l2...
930
931
932
  
  	chan->data = sk;
  	chan->ops = &l2cap_chan_ops;
bb58f747e   Gustavo F. Padovan   Bluetooth: Initia...
933
934
935
936
937
938
939
  }
  
  static struct proto l2cap_proto = {
  	.name		= "L2CAP",
  	.owner		= THIS_MODULE,
  	.obj_size	= sizeof(struct l2cap_pinfo)
  };
80808e431   Gustavo F. Padovan   Bluetooth: Add l2...
940
  static struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock, int proto, gfp_t prio)
bb58f747e   Gustavo F. Padovan   Bluetooth: Initia...
941
942
  {
  	struct sock *sk;
dc50a06da   Gustavo F. Padovan   Bluetooth: Merge ...
943
  	struct l2cap_chan *chan;
bb58f747e   Gustavo F. Padovan   Bluetooth: Initia...
944
945
946
947
948
949
950
951
952
  
  	sk = sk_alloc(net, PF_BLUETOOTH, prio, &l2cap_proto);
  	if (!sk)
  		return NULL;
  
  	sock_init_data(sock, sk);
  	INIT_LIST_HEAD(&bt_sk(sk)->accept_q);
  
  	sk->sk_destruct = l2cap_sock_destruct;
6be6b11f0   Chen Ganir   Bluetooth: Fixed ...
953
  	sk->sk_sndtimeo = L2CAP_CONN_TIMEOUT;
bb58f747e   Gustavo F. Padovan   Bluetooth: Initia...
954
955
956
957
958
  
  	sock_reset_flag(sk, SOCK_ZAPPED);
  
  	sk->sk_protocol = proto;
  	sk->sk_state = BT_OPEN;
dc50a06da   Gustavo F. Padovan   Bluetooth: Merge ...
959
960
961
962
963
964
965
  	chan = l2cap_chan_create(sk);
  	if (!chan) {
  		l2cap_sock_kill(sk);
  		return NULL;
  	}
  
  	l2cap_pi(sk)->chan = chan;
bb58f747e   Gustavo F. Padovan   Bluetooth: Initia...
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
  	return sk;
  }
  
  static int l2cap_sock_create(struct net *net, struct socket *sock, int protocol,
  			     int kern)
  {
  	struct sock *sk;
  
  	BT_DBG("sock %p", sock);
  
  	sock->state = SS_UNCONNECTED;
  
  	if (sock->type != SOCK_SEQPACKET && sock->type != SOCK_STREAM &&
  			sock->type != SOCK_DGRAM && sock->type != SOCK_RAW)
  		return -ESOCKTNOSUPPORT;
  
  	if (sock->type == SOCK_RAW && !kern && !capable(CAP_NET_RAW))
  		return -EPERM;
  
  	sock->ops = &l2cap_sock_ops;
  
  	sk = l2cap_sock_alloc(net, sock, protocol, GFP_ATOMIC);
  	if (!sk)
  		return -ENOMEM;
  
  	l2cap_sock_init(sk, NULL);
  	return 0;
  }
cf2f90f59   Gustavo F. Padovan   Bluetooth: Don't ...
994
  static const struct proto_ops l2cap_sock_ops = {
65390587c   Gustavo F. Padovan   Bluetooth: move l...
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
  	.family		= PF_BLUETOOTH,
  	.owner		= THIS_MODULE,
  	.release	= l2cap_sock_release,
  	.bind		= l2cap_sock_bind,
  	.connect	= l2cap_sock_connect,
  	.listen		= l2cap_sock_listen,
  	.accept		= l2cap_sock_accept,
  	.getname	= l2cap_sock_getname,
  	.sendmsg	= l2cap_sock_sendmsg,
  	.recvmsg	= l2cap_sock_recvmsg,
  	.poll		= bt_sock_poll,
  	.ioctl		= bt_sock_ioctl,
  	.mmap		= sock_no_mmap,
  	.socketpair	= sock_no_socketpair,
  	.shutdown	= l2cap_sock_shutdown,
  	.setsockopt	= l2cap_sock_setsockopt,
  	.getsockopt	= l2cap_sock_getsockopt
  };
bb58f747e   Gustavo F. Padovan   Bluetooth: Initia...
1013
1014
1015
1016
1017
1018
1019
1020
  static const struct net_proto_family l2cap_sock_family_ops = {
  	.family	= PF_BLUETOOTH,
  	.owner	= THIS_MODULE,
  	.create	= l2cap_sock_create,
  };
  
  int __init l2cap_init_sockets(void)
  {
e2174ca43   Gustavo F. Padovan   Bluetooth: fix er...
1021
  	int err;
bb58f747e   Gustavo F. Padovan   Bluetooth: Initia...
1022

e2174ca43   Gustavo F. Padovan   Bluetooth: fix er...
1023
1024
1025
  	err = proto_register(&l2cap_proto, 0);
  	if (err < 0)
  		return err;
bb58f747e   Gustavo F. Padovan   Bluetooth: Initia...
1026

e2174ca43   Gustavo F. Padovan   Bluetooth: fix er...
1027
1028
1029
  	err = bt_sock_register(BTPROTO_L2CAP, &l2cap_sock_family_ops);
  	if (err < 0)
  		goto error;
bb58f747e   Gustavo F. Padovan   Bluetooth: Initia...
1030

e2174ca43   Gustavo F. Padovan   Bluetooth: fix er...
1031
  	BT_INFO("L2CAP socket layer initialized");
bb58f747e   Gustavo F. Padovan   Bluetooth: Initia...
1032

e2174ca43   Gustavo F. Padovan   Bluetooth: fix er...
1033
  	return 0;
bb58f747e   Gustavo F. Padovan   Bluetooth: Initia...
1034
1035
  
  error:
e2174ca43   Gustavo F. Padovan   Bluetooth: fix er...
1036
1037
1038
  	BT_ERR("L2CAP socket registration failed");
  	proto_unregister(&l2cap_proto);
  	return err;
bb58f747e   Gustavo F. Padovan   Bluetooth: Initia...
1039
1040
1041
1042
  }
  
  void l2cap_cleanup_sockets(void)
  {
e2174ca43   Gustavo F. Padovan   Bluetooth: fix er...
1043
1044
  	if (bt_sock_unregister(BTPROTO_L2CAP) < 0)
  		BT_ERR("L2CAP socket unregistration failed");
bb58f747e   Gustavo F. Padovan   Bluetooth: Initia...
1045

e2174ca43   Gustavo F. Padovan   Bluetooth: fix er...
1046
  	proto_unregister(&l2cap_proto);
bb58f747e   Gustavo F. Padovan   Bluetooth: Initia...
1047
  }