Blame view

net/bluetooth/rfcomm/sock.c 22.6 KB
8e87d1425   YOSHIFUJI Hideaki   [NET] BLUETOOTH: ...
1
  /*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2
3
4
5
6
7
8
9
10
11
12
13
     RFCOMM implementation for Linux Bluetooth stack (BlueZ).
     Copyright (C) 2002 Maxim Krasnyansky <maxk@qualcomm.com>
     Copyright (C) 2002 Marcel Holtmann <marcel@holtmann.org>
  
     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
8e87d1425   YOSHIFUJI Hideaki   [NET] BLUETOOTH: ...
14
15
16
     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
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
17
     OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
8e87d1425   YOSHIFUJI Hideaki   [NET] BLUETOOTH: ...
18
19
     ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
     COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
20
21
22
23
24
     SOFTWARE IS DISCLAIMED.
  */
  
  /*
   * RFCOMM sockets.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
25
   */
8c520a599   Gustavo Padovan   Bluetooth: Remove...
26
  #include <linux/export.h>
aef7d97cc   Marcel Holtmann   Bluetooth: Conver...
27
  #include <linux/debugfs.h>
174cd4b1e   Ingo Molnar   sched/headers: Pr...
28
  #include <linux/sched/signal.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
29
30
31
32
33
  
  #include <net/bluetooth/bluetooth.h>
  #include <net/bluetooth/hci_core.h>
  #include <net/bluetooth/l2cap.h>
  #include <net/bluetooth/rfcomm.h>
90ddc4f04   Eric Dumazet   [NET]: move struc...
34
  static const struct proto_ops rfcomm_sock_ops;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
35
36
  
  static struct bt_sock_list rfcomm_sk_list = {
d5fb2962c   Robert P. J. Day   bluetooth: replac...
37
  	.lock = __RW_LOCK_UNLOCKED(rfcomm_sk_list.lock)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
  };
  
  static void rfcomm_sock_close(struct sock *sk);
  static void rfcomm_sock_kill(struct sock *sk);
  
  /* ---- DLC callbacks ----
   *
   * called under rfcomm_dlc_lock()
   */
  static void rfcomm_sk_data_ready(struct rfcomm_dlc *d, struct sk_buff *skb)
  {
  	struct sock *sk = d->owner;
  	if (!sk)
  		return;
  
  	atomic_add(skb->len, &sk->sk_rmem_alloc);
  	skb_queue_tail(&sk->sk_receive_queue, skb);
676d23690   David S. Miller   net: Fix use afte...
55
  	sk->sk_data_ready(sk);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
56
57
58
59
60
61
62
63
  
  	if (atomic_read(&sk->sk_rmem_alloc) >= sk->sk_rcvbuf)
  		rfcomm_dlc_throttle(d);
  }
  
  static void rfcomm_sk_state_change(struct rfcomm_dlc *d, int err)
  {
  	struct sock *sk = d->owner, *parent;
fad003b6c   Gustavo F. Padovan   Bluetooth: Fix in...
64
  	unsigned long flags;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
65
66
67
68
  	if (!sk)
  		return;
  
  	BT_DBG("dlc %p state %ld err %d", d, d->state, err);
fad003b6c   Gustavo F. Padovan   Bluetooth: Fix in...
69
  	local_irq_save(flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
70
71
72
73
74
75
76
77
78
79
80
81
82
  	bh_lock_sock(sk);
  
  	if (err)
  		sk->sk_err = err;
  
  	sk->sk_state = d->state;
  
  	parent = bt_sk(sk)->parent;
  	if (parent) {
  		if (d->state == BT_CLOSED) {
  			sock_set_flag(sk, SOCK_ZAPPED);
  			bt_accept_unlink(sk);
  		}
676d23690   David S. Miller   net: Fix use afte...
83
  		parent->sk_data_ready(parent);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
84
85
  	} else {
  		if (d->state == BT_CONNECTED)
94a86df01   Marcel Holtmann   Bluetooth: Store ...
86
87
  			rfcomm_session_getaddr(d->session,
  					       &rfcomm_pi(sk)->src, NULL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
88
89
90
91
  		sk->sk_state_change(sk);
  	}
  
  	bh_unlock_sock(sk);
fad003b6c   Gustavo F. Padovan   Bluetooth: Fix in...
92
  	local_irq_restore(flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
93
94
95
96
97
98
99
100
101
102
103
  
  	if (parent && sock_flag(sk, SOCK_ZAPPED)) {
  		/* We have to drop DLC lock here, otherwise
  		 * rfcomm_sock_destruct() will dead lock. */
  		rfcomm_dlc_unlock(d);
  		rfcomm_sock_kill(sk);
  		rfcomm_dlc_lock(d);
  	}
  }
  
  /* ---- Socket functions ---- */
b1765e7af   Andrzej Kaczmarek   Bluetooth: Fix ch...
104
  static struct sock *__rfcomm_get_listen_sock_by_addr(u8 channel, bdaddr_t *src)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
105
106
  {
  	struct sock *sk = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
107

b67bfe0d4   Sasha Levin   hlist: drop the n...
108
  	sk_for_each(sk, &rfcomm_sk_list.head) {
b1765e7af   Andrzej Kaczmarek   Bluetooth: Fix ch...
109
110
111
112
113
114
115
  		if (rfcomm_pi(sk)->channel != channel)
  			continue;
  
  		if (bacmp(&rfcomm_pi(sk)->src, src))
  			continue;
  
  		if (sk->sk_state == BT_BOUND || sk->sk_state == BT_LISTEN)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
116
117
  			break;
  	}
b67bfe0d4   Sasha Levin   hlist: drop the n...
118
  	return sk ? sk : NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
119
120
121
122
123
  }
  
  /* Find socket with channel and source bdaddr.
   * Returns closest match.
   */
eeb366564   Gustavo F. Padovan   Bluetooth: Get ri...
124
  static struct sock *rfcomm_get_sock_by_channel(int state, u8 channel, bdaddr_t *src)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
125
126
  {
  	struct sock *sk = NULL, *sk1 = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
127

eeb366564   Gustavo F. Padovan   Bluetooth: Get ri...
128
  	read_lock(&rfcomm_sk_list.lock);
b67bfe0d4   Sasha Levin   hlist: drop the n...
129
  	sk_for_each(sk, &rfcomm_sk_list.head) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
130
131
132
133
134
  		if (state && sk->sk_state != state)
  			continue;
  
  		if (rfcomm_pi(sk)->channel == channel) {
  			/* Exact match. */
94a86df01   Marcel Holtmann   Bluetooth: Store ...
135
  			if (!bacmp(&rfcomm_pi(sk)->src, src))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
136
137
138
  				break;
  
  			/* Closest match */
94a86df01   Marcel Holtmann   Bluetooth: Store ...
139
  			if (!bacmp(&rfcomm_pi(sk)->src, BDADDR_ANY))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
140
141
142
  				sk1 = sk;
  		}
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
143

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
144
  	read_unlock(&rfcomm_sk_list.lock);
eeb366564   Gustavo F. Padovan   Bluetooth: Get ri...
145

b67bfe0d4   Sasha Levin   hlist: drop the n...
146
  	return sk ? sk : sk1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
  }
  
  static void rfcomm_sock_destruct(struct sock *sk)
  {
  	struct rfcomm_dlc *d = rfcomm_pi(sk)->dlc;
  
  	BT_DBG("sk %p dlc %p", sk, d);
  
  	skb_queue_purge(&sk->sk_receive_queue);
  	skb_queue_purge(&sk->sk_write_queue);
  
  	rfcomm_dlc_lock(d);
  	rfcomm_pi(sk)->dlc = NULL;
  
  	/* Detach DLC if it's owned by this socket */
  	if (d->owner == sk)
  		d->owner = NULL;
  	rfcomm_dlc_unlock(d);
  
  	rfcomm_dlc_put(d);
  }
  
  static void rfcomm_sock_cleanup_listen(struct sock *parent)
  {
  	struct sock *sk;
  
  	BT_DBG("parent %p", parent);
  
  	/* Close not yet accepted dlcs */
  	while ((sk = bt_accept_dequeue(parent, NULL))) {
  		rfcomm_sock_close(sk);
  		rfcomm_sock_kill(sk);
  	}
  
  	parent->sk_state  = BT_CLOSED;
  	sock_set_flag(parent, SOCK_ZAPPED);
  }
  
  /* Kill socket (only if zapped and orphan)
   * Must be called on unlocked socket.
   */
  static void rfcomm_sock_kill(struct sock *sk)
  {
  	if (!sock_flag(sk, SOCK_ZAPPED) || sk->sk_socket)
  		return;
  
  	BT_DBG("sk %p state %d refcnt %d", sk, sk->sk_state, atomic_read(&sk->sk_refcnt));
  
  	/* Kill poor orphan */
  	bt_sock_unlink(&rfcomm_sk_list, sk);
  	sock_set_flag(sk, SOCK_DEAD);
  	sock_put(sk);
  }
  
  static void __rfcomm_sock_close(struct sock *sk)
  {
  	struct rfcomm_dlc *d = rfcomm_pi(sk)->dlc;
  
  	BT_DBG("sk %p state %d socket %p", sk, sk->sk_state, sk->sk_socket);
  
  	switch (sk->sk_state) {
  	case BT_LISTEN:
  		rfcomm_sock_cleanup_listen(sk);
  		break;
  
  	case BT_CONNECT:
  	case BT_CONNECT2:
  	case BT_CONFIG:
  	case BT_CONNECTED:
  		rfcomm_dlc_close(d, 0);
  
  	default:
  		sock_set_flag(sk, SOCK_ZAPPED);
  		break;
  	}
  }
  
  /* Close socket.
   * Must be called on unlocked socket.
   */
  static void rfcomm_sock_close(struct sock *sk)
  {
  	lock_sock(sk);
  	__rfcomm_sock_close(sk);
  	release_sock(sk);
  }
  
  static void rfcomm_sock_init(struct sock *sk, struct sock *parent)
  {
  	struct rfcomm_pinfo *pi = rfcomm_pi(sk);
  
  	BT_DBG("sk %p", sk);
  
  	if (parent) {
  		sk->sk_type = parent->sk_type;
c5daa683f   Gustavo Padovan   Bluetooth: Create...
242
243
  		pi->dlc->defer_setup = test_bit(BT_SK_DEFER_SETUP,
  						&bt_sk(parent)->flags);
9f2c8a03f   Marcel Holtmann   Bluetooth: Replac...
244
245
246
  
  		pi->sec_level = rfcomm_pi(parent)->sec_level;
  		pi->role_switch = rfcomm_pi(parent)->role_switch;
6230c9b4f   Paul Moore   bluetooth: Proper...
247
248
  
  		security_sk_clone(parent, sk);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
249
  	} else {
bb23c0ab8   Marcel Holtmann   Bluetooth: Add su...
250
  		pi->dlc->defer_setup = 0;
9f2c8a03f   Marcel Holtmann   Bluetooth: Replac...
251
252
253
  
  		pi->sec_level = BT_SECURITY_LOW;
  		pi->role_switch = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
254
  	}
9f2c8a03f   Marcel Holtmann   Bluetooth: Replac...
255
256
  	pi->dlc->sec_level = pi->sec_level;
  	pi->dlc->role_switch = pi->role_switch;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
257
258
259
260
261
262
263
  }
  
  static struct proto rfcomm_proto = {
  	.name		= "RFCOMM",
  	.owner		= THIS_MODULE,
  	.obj_size	= sizeof(struct rfcomm_pinfo)
  };
11aa9c28b   Eric W. Biederman   net: Pass kern fr...
264
  static struct sock *rfcomm_sock_alloc(struct net *net, struct socket *sock, int proto, gfp_t prio, int kern)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
265
266
267
  {
  	struct rfcomm_dlc *d;
  	struct sock *sk;
11aa9c28b   Eric W. Biederman   net: Pass kern fr...
268
  	sk = sk_alloc(net, PF_BLUETOOTH, prio, &rfcomm_proto, kern);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
  	if (!sk)
  		return NULL;
  
  	sock_init_data(sock, sk);
  	INIT_LIST_HEAD(&bt_sk(sk)->accept_q);
  
  	d = rfcomm_dlc_alloc(prio);
  	if (!d) {
  		sk_free(sk);
  		return NULL;
  	}
  
  	d->data_ready   = rfcomm_sk_data_ready;
  	d->state_change = rfcomm_sk_state_change;
  
  	rfcomm_pi(sk)->dlc = d;
  	d->owner = sk;
  
  	sk->sk_destruct = rfcomm_sock_destruct;
  	sk->sk_sndtimeo = RFCOMM_CONN_TIMEOUT;
77db19805   Marcel Holtmann   [Bluetooth] Enfor...
289
290
  	sk->sk_sndbuf = RFCOMM_MAX_CREDITS * RFCOMM_DEFAULT_MTU * 10;
  	sk->sk_rcvbuf = RFCOMM_MAX_CREDITS * RFCOMM_DEFAULT_MTU * 10;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
291
292
293
294
  
  	sock_reset_flag(sk, SOCK_ZAPPED);
  
  	sk->sk_protocol = proto;
77db19805   Marcel Holtmann   [Bluetooth] Enfor...
295
  	sk->sk_state    = BT_OPEN;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
296
297
298
299
300
301
  
  	bt_sock_link(&rfcomm_sk_list, sk);
  
  	BT_DBG("sk %p", sk);
  	return sk;
  }
3f378b684   Eric Paris   net: pass kern to...
302
303
  static int rfcomm_sock_create(struct net *net, struct socket *sock,
  			      int protocol, int kern)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
304
305
306
307
308
309
310
311
312
313
314
  {
  	struct sock *sk;
  
  	BT_DBG("sock %p", sock);
  
  	sock->state = SS_UNCONNECTED;
  
  	if (sock->type != SOCK_STREAM && sock->type != SOCK_RAW)
  		return -ESOCKTNOSUPPORT;
  
  	sock->ops = &rfcomm_sock_ops;
11aa9c28b   Eric W. Biederman   net: Pass kern fr...
315
  	sk = rfcomm_sock_alloc(net, sock, protocol, GFP_ATOMIC, kern);
74da626a1   Marcel Holtmann   [Bluetooth] Add l...
316
  	if (!sk)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
317
318
319
320
321
322
323
324
  		return -ENOMEM;
  
  	rfcomm_sock_init(sk, NULL);
  	return 0;
  }
  
  static int rfcomm_sock_bind(struct socket *sock, struct sockaddr *addr, int addr_len)
  {
951b6a071   Jaganath Kanakkassery   Bluetooth: Fix po...
325
  	struct sockaddr_rc sa;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
326
  	struct sock *sk = sock->sk;
951b6a071   Jaganath Kanakkassery   Bluetooth: Fix po...
327
  	int len, err = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
328
329
330
  
  	if (!addr || addr->sa_family != AF_BLUETOOTH)
  		return -EINVAL;
951b6a071   Jaganath Kanakkassery   Bluetooth: Fix po...
331
332
333
334
335
  	memset(&sa, 0, sizeof(sa));
  	len = min_t(unsigned int, sizeof(sa), addr_len);
  	memcpy(&sa, addr, len);
  
  	BT_DBG("sk %p %pMR", sk, &sa.rc_bdaddr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
336
337
338
339
340
341
  	lock_sock(sk);
  
  	if (sk->sk_state != BT_OPEN) {
  		err = -EBADFD;
  		goto done;
  	}
354d28d5f   Marcel Holtmann   [Bluetooth] Preve...
342
343
344
345
  	if (sk->sk_type != SOCK_STREAM) {
  		err = -EINVAL;
  		goto done;
  	}
95ca83f42   Gustavo F. Padovan   Bluetooth: Fix co...
346
  	write_lock(&rfcomm_sk_list.lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
347

951b6a071   Jaganath Kanakkassery   Bluetooth: Fix po...
348
349
  	if (sa.rc_channel &&
  	    __rfcomm_get_listen_sock_by_addr(sa.rc_channel, &sa.rc_bdaddr)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
350
351
352
  		err = -EADDRINUSE;
  	} else {
  		/* Save source address */
951b6a071   Jaganath Kanakkassery   Bluetooth: Fix po...
353
354
  		bacpy(&rfcomm_pi(sk)->src, &sa.rc_bdaddr);
  		rfcomm_pi(sk)->channel = sa.rc_channel;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
355
356
  		sk->sk_state = BT_BOUND;
  	}
95ca83f42   Gustavo F. Padovan   Bluetooth: Fix co...
357
  	write_unlock(&rfcomm_sk_list.lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
358
359
360
361
362
363
364
365
366
367
368
369
370
371
  
  done:
  	release_sock(sk);
  	return err;
  }
  
  static int rfcomm_sock_connect(struct socket *sock, struct sockaddr *addr, int alen, int flags)
  {
  	struct sockaddr_rc *sa = (struct sockaddr_rc *) addr;
  	struct sock *sk = sock->sk;
  	struct rfcomm_dlc *d = rfcomm_pi(sk)->dlc;
  	int err = 0;
  
  	BT_DBG("sk %p", sk);
6503d9616   Changli Gao   net: check the le...
372
373
  	if (alen < sizeof(struct sockaddr_rc) ||
  	    addr->sa_family != AF_BLUETOOTH)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
374
  		return -EINVAL;
354d28d5f   Marcel Holtmann   [Bluetooth] Preve...
375
  	lock_sock(sk);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
376

354d28d5f   Marcel Holtmann   [Bluetooth] Preve...
377
378
379
380
  	if (sk->sk_state != BT_OPEN && sk->sk_state != BT_BOUND) {
  		err = -EBADFD;
  		goto done;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
381

354d28d5f   Marcel Holtmann   [Bluetooth] Preve...
382
383
384
385
  	if (sk->sk_type != SOCK_STREAM) {
  		err = -EINVAL;
  		goto done;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
386
387
  
  	sk->sk_state = BT_CONNECT;
94a86df01   Marcel Holtmann   Bluetooth: Store ...
388
  	bacpy(&rfcomm_pi(sk)->dst, &sa->rc_bdaddr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
389
  	rfcomm_pi(sk)->channel = sa->rc_channel;
9f2c8a03f   Marcel Holtmann   Bluetooth: Replac...
390
391
  	d->sec_level = rfcomm_pi(sk)->sec_level;
  	d->role_switch = rfcomm_pi(sk)->role_switch;
77db19805   Marcel Holtmann   [Bluetooth] Enfor...
392

94a86df01   Marcel Holtmann   Bluetooth: Store ...
393
394
  	err = rfcomm_dlc_open(d, &rfcomm_pi(sk)->src, &sa->rc_bdaddr,
  			      sa->rc_channel);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
395
396
397
  	if (!err)
  		err = bt_sock_wait_state(sk, BT_CONNECTED,
  				sock_sndtimeo(sk, flags & O_NONBLOCK));
354d28d5f   Marcel Holtmann   [Bluetooth] Preve...
398
  done:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
  	release_sock(sk);
  	return err;
  }
  
  static int rfcomm_sock_listen(struct socket *sock, int backlog)
  {
  	struct sock *sk = sock->sk;
  	int err = 0;
  
  	BT_DBG("sk %p backlog %d", sk, backlog);
  
  	lock_sock(sk);
  
  	if (sk->sk_state != BT_BOUND) {
  		err = -EBADFD;
  		goto done;
  	}
354d28d5f   Marcel Holtmann   [Bluetooth] Preve...
416
417
418
419
  	if (sk->sk_type != SOCK_STREAM) {
  		err = -EINVAL;
  		goto done;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
420
  	if (!rfcomm_pi(sk)->channel) {
94a86df01   Marcel Holtmann   Bluetooth: Store ...
421
  		bdaddr_t *src = &rfcomm_pi(sk)->src;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
422
423
424
  		u8 channel;
  
  		err = -EINVAL;
95ca83f42   Gustavo F. Padovan   Bluetooth: Fix co...
425
  		write_lock(&rfcomm_sk_list.lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
426
427
  
  		for (channel = 1; channel < 31; channel++)
b1765e7af   Andrzej Kaczmarek   Bluetooth: Fix ch...
428
  			if (!__rfcomm_get_listen_sock_by_addr(channel, src)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
429
430
431
432
  				rfcomm_pi(sk)->channel = channel;
  				err = 0;
  				break;
  			}
95ca83f42   Gustavo F. Padovan   Bluetooth: Fix co...
433
  		write_unlock(&rfcomm_sk_list.lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
434
435
436
437
438
439
440
441
442
443
444
445
446
  
  		if (err < 0)
  			goto done;
  	}
  
  	sk->sk_max_ack_backlog = backlog;
  	sk->sk_ack_backlog = 0;
  	sk->sk_state = BT_LISTEN;
  
  done:
  	release_sock(sk);
  	return err;
  }
cdfbabfb2   David Howells   net: Work around ...
447
448
  static int rfcomm_sock_accept(struct socket *sock, struct socket *newsock, int flags,
  			      bool kern)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
449
  {
dfb2fae7c   Peter Hurley   Bluetooth: Fix ne...
450
  	DEFINE_WAIT_FUNC(wait, woken_wake_function);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
451
452
453
  	struct sock *sk = sock->sk, *nsk;
  	long timeo;
  	int err = 0;
dc2a0e20f   Gustavo Padovan   Bluetooth: Add mi...
454
  	lock_sock_nested(sk, SINGLE_DEPTH_NESTING);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
455

354d28d5f   Marcel Holtmann   [Bluetooth] Preve...
456
457
458
459
  	if (sk->sk_type != SOCK_STREAM) {
  		err = -EINVAL;
  		goto done;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
460
461
462
463
464
  	timeo = sock_rcvtimeo(sk, flags & O_NONBLOCK);
  
  	BT_DBG("sk %p timeo %ld", sk, timeo);
  
  	/* Wait for an incoming connection. (wake-one). */
aa3951451   Eric Dumazet   net: sk_sleep() h...
465
  	add_wait_queue_exclusive(sk_sleep(sk), &wait);
950e2d51e   Peter Hurley   Bluetooth: rfcomm...
466
  	while (1) {
950e2d51e   Peter Hurley   Bluetooth: rfcomm...
467
468
  		if (sk->sk_state != BT_LISTEN) {
  			err = -EBADFD;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
469
470
  			break;
  		}
950e2d51e   Peter Hurley   Bluetooth: rfcomm...
471
472
473
  		nsk = bt_accept_dequeue(sk, newsock);
  		if (nsk)
  			break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
474

950e2d51e   Peter Hurley   Bluetooth: rfcomm...
475
476
  		if (!timeo) {
  			err = -EAGAIN;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
477
478
479
480
481
482
483
  			break;
  		}
  
  		if (signal_pending(current)) {
  			err = sock_intr_errno(timeo);
  			break;
  		}
950e2d51e   Peter Hurley   Bluetooth: rfcomm...
484
485
  
  		release_sock(sk);
dfb2fae7c   Peter Hurley   Bluetooth: Fix ne...
486
487
  
  		timeo = wait_woken(&wait, TASK_INTERRUPTIBLE, timeo);
dc2a0e20f   Gustavo Padovan   Bluetooth: Add mi...
488
  		lock_sock_nested(sk, SINGLE_DEPTH_NESTING);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
489
  	}
aa3951451   Eric Dumazet   net: sk_sleep() h...
490
  	remove_wait_queue(sk_sleep(sk), &wait);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
  
  	if (err)
  		goto done;
  
  	newsock->state = SS_CONNECTED;
  
  	BT_DBG("new socket %p", nsk);
  
  done:
  	release_sock(sk);
  	return err;
  }
  
  static int rfcomm_sock_getname(struct socket *sock, struct sockaddr *addr, int *len, int peer)
  {
  	struct sockaddr_rc *sa = (struct sockaddr_rc *) addr;
  	struct sock *sk = sock->sk;
  
  	BT_DBG("sock %p, sk %p", sock, sk);
e8b1ab9e6   Johan Hedberg   Bluetooth: Fix re...
510
511
  	if (peer && sk->sk_state != BT_CONNECTED &&
  	    sk->sk_state != BT_CONNECT && sk->sk_state != BT_CONNECT2)
35364c99d   Johan Hedberg   Bluetooth: Refuse...
512
  		return -ENOTCONN;
9344a9729   Mathias Krause   Bluetooth: RFCOMM...
513
  	memset(sa, 0, sizeof(*sa));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
514
515
516
  	sa->rc_family  = AF_BLUETOOTH;
  	sa->rc_channel = rfcomm_pi(sk)->channel;
  	if (peer)
94a86df01   Marcel Holtmann   Bluetooth: Store ...
517
  		bacpy(&sa->rc_bdaddr, &rfcomm_pi(sk)->dst);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
518
  	else
94a86df01   Marcel Holtmann   Bluetooth: Store ...
519
  		bacpy(&sa->rc_bdaddr, &rfcomm_pi(sk)->src);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
520
521
522
523
  
  	*len = sizeof(struct sockaddr_rc);
  	return 0;
  }
1b7841404   Ying Xue   net: Remove iocb ...
524
525
  static int rfcomm_sock_sendmsg(struct socket *sock, struct msghdr *msg,
  			       size_t len)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
526
527
528
529
  {
  	struct sock *sk = sock->sk;
  	struct rfcomm_dlc *d = rfcomm_pi(sk)->dlc;
  	struct sk_buff *skb;
e793dcf08   Johan Hedberg   Bluetooth: Fix wa...
530
  	int sent;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
531

bb23c0ab8   Marcel Holtmann   Bluetooth: Add su...
532
533
  	if (test_bit(RFCOMM_DEFER_SETUP, &d->flags))
  		return -ENOTCONN;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
534
535
536
537
538
539
540
541
542
  	if (msg->msg_flags & MSG_OOB)
  		return -EOPNOTSUPP;
  
  	if (sk->sk_shutdown & SEND_SHUTDOWN)
  		return -EPIPE;
  
  	BT_DBG("sock %p, sk %p", sock, sk);
  
  	lock_sock(sk);
e793dcf08   Johan Hedberg   Bluetooth: Fix wa...
543
544
545
  	sent = bt_sock_wait_ready(sk, msg->msg_flags);
  	if (sent)
  		goto done;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
546
547
  	while (len) {
  		size_t size = min_t(size_t, len, d->mtu);
4d6a2188b   Marcel Holtmann   [Bluetooth] Fix u...
548
  		int err;
8e87d1425   YOSHIFUJI Hideaki   [NET] BLUETOOTH: ...
549

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
550
551
  		skb = sock_alloc_send_skb(sk, size + RFCOMM_SKB_RESERVE,
  				msg->msg_flags & MSG_DONTWAIT, &err);
91aa35a5a   Victor Shcherbatyuk   Bluetooth: Fix is...
552
553
554
  		if (!skb) {
  			if (sent == 0)
  				sent = err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
555
  			break;
91aa35a5a   Victor Shcherbatyuk   Bluetooth: Fix is...
556
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
557
  		skb_reserve(skb, RFCOMM_SKB_HEAD_RESERVE);
6ce8e9ce5   Al Viro   new helper: memcp...
558
  		err = memcpy_from_msg(skb_put(skb, size), msg, size);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
559
560
  		if (err) {
  			kfree_skb(skb);
4d6a2188b   Marcel Holtmann   [Bluetooth] Fix u...
561
562
  			if (sent == 0)
  				sent = err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
563
564
  			break;
  		}
262038fcb   Luiz Augusto von Dentz   Bluetooth: make u...
565
  		skb->priority = sk->sk_priority;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
566
567
568
  		err = rfcomm_dlc_send(d, skb);
  		if (err < 0) {
  			kfree_skb(skb);
4d6a2188b   Marcel Holtmann   [Bluetooth] Fix u...
569
570
  			if (sent == 0)
  				sent = err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
571
572
573
574
575
576
  			break;
  		}
  
  		sent += size;
  		len  -= size;
  	}
e793dcf08   Johan Hedberg   Bluetooth: Fix wa...
577
  done:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
578
  	release_sock(sk);
4d6a2188b   Marcel Holtmann   [Bluetooth] Fix u...
579
  	return sent;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
580
  }
1b7841404   Ying Xue   net: Remove iocb ...
581
582
  static int rfcomm_sock_recvmsg(struct socket *sock, struct msghdr *msg,
  			       size_t size, int flags)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
583
584
  {
  	struct sock *sk = sock->sk;
bb23c0ab8   Marcel Holtmann   Bluetooth: Add su...
585
  	struct rfcomm_dlc *d = rfcomm_pi(sk)->dlc;
3d7d01dff   Mat Martineau   Bluetooth: Use co...
586
  	int len;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
587

bb23c0ab8   Marcel Holtmann   Bluetooth: Add su...
588
589
590
591
  	if (test_and_clear_bit(RFCOMM_DEFER_SETUP, &d->flags)) {
  		rfcomm_dlc_accept(d);
  		return 0;
  	}
1b7841404   Ying Xue   net: Remove iocb ...
592
  	len = bt_sock_stream_recvmsg(sock, msg, size, flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
593
594
  
  	lock_sock(sk);
3d7d01dff   Mat Martineau   Bluetooth: Use co...
595
596
  	if (!(flags & MSG_PEEK) && len > 0)
  		atomic_sub(len, &sk->sk_rmem_alloc);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
597

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
598
599
  	if (atomic_read(&sk->sk_rmem_alloc) <= (sk->sk_rcvbuf >> 2))
  		rfcomm_dlc_unthrottle(rfcomm_pi(sk)->dlc);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
600
  	release_sock(sk);
3d7d01dff   Mat Martineau   Bluetooth: Use co...
601
602
  
  	return len;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
603
  }
b7058842c   David S. Miller   net: Make setsock...
604
  static int rfcomm_sock_setsockopt_old(struct socket *sock, int optname, char __user *optval, unsigned int optlen)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
  {
  	struct sock *sk = sock->sk;
  	int err = 0;
  	u32 opt;
  
  	BT_DBG("sk %p", sk);
  
  	lock_sock(sk);
  
  	switch (optname) {
  	case RFCOMM_LM:
  		if (get_user(opt, (u32 __user *) optval)) {
  			err = -EFAULT;
  			break;
  		}
2c068e0b9   Marcel Holtmann   Bluetooth: Handle...
620
621
622
623
  		if (opt & RFCOMM_LM_FIPS) {
  			err = -EINVAL;
  			break;
  		}
9f2c8a03f   Marcel Holtmann   Bluetooth: Replac...
624
625
626
627
628
629
630
631
  		if (opt & RFCOMM_LM_AUTH)
  			rfcomm_pi(sk)->sec_level = BT_SECURITY_LOW;
  		if (opt & RFCOMM_LM_ENCRYPT)
  			rfcomm_pi(sk)->sec_level = BT_SECURITY_MEDIUM;
  		if (opt & RFCOMM_LM_SECURE)
  			rfcomm_pi(sk)->sec_level = BT_SECURITY_HIGH;
  
  		rfcomm_pi(sk)->role_switch = (opt & RFCOMM_LM_MASTER);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
632
633
634
635
636
637
638
639
640
641
  		break;
  
  	default:
  		err = -ENOPROTOOPT;
  		break;
  	}
  
  	release_sock(sk);
  	return err;
  }
b7058842c   David S. Miller   net: Make setsock...
642
  static int rfcomm_sock_setsockopt(struct socket *sock, int level, int optname, char __user *optval, unsigned int optlen)
d58daf42d   Marcel Holtmann   Bluetooth: Prepar...
643
644
  {
  	struct sock *sk = sock->sk;
9f2c8a03f   Marcel Holtmann   Bluetooth: Replac...
645
  	struct bt_security sec;
d0fad89da   Stephen Boyd   Bluetooth: Silenc...
646
647
  	int err = 0;
  	size_t len;
bb23c0ab8   Marcel Holtmann   Bluetooth: Add su...
648
  	u32 opt;
d58daf42d   Marcel Holtmann   Bluetooth: Prepar...
649
650
651
652
653
  
  	BT_DBG("sk %p", sk);
  
  	if (level == SOL_RFCOMM)
  		return rfcomm_sock_setsockopt_old(sock, optname, optval, optlen);
0588d94fd   Marcel Holtmann   Bluetooth: Restri...
654
655
  	if (level != SOL_BLUETOOTH)
  		return -ENOPROTOOPT;
d58daf42d   Marcel Holtmann   Bluetooth: Prepar...
656
657
658
  	lock_sock(sk);
  
  	switch (optname) {
9f2c8a03f   Marcel Holtmann   Bluetooth: Replac...
659
  	case BT_SECURITY:
0588d94fd   Marcel Holtmann   Bluetooth: Restri...
660
661
662
663
  		if (sk->sk_type != SOCK_STREAM) {
  			err = -EINVAL;
  			break;
  		}
9f2c8a03f   Marcel Holtmann   Bluetooth: Replac...
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
  		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_HIGH) {
  			err = -EINVAL;
  			break;
  		}
  
  		rfcomm_pi(sk)->sec_level = sec.level;
  		break;
bb23c0ab8   Marcel Holtmann   Bluetooth: Add su...
679
680
681
682
683
684
685
686
687
688
  	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;
  		}
c5daa683f   Gustavo Padovan   Bluetooth: Create...
689
690
691
692
  		if (opt)
  			set_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags);
  		else
  			clear_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags);
bb23c0ab8   Marcel Holtmann   Bluetooth: Add su...
693
  		break;
d58daf42d   Marcel Holtmann   Bluetooth: Prepar...
694
695
696
697
698
699
700
701
702
703
  	default:
  		err = -ENOPROTOOPT;
  		break;
  	}
  
  	release_sock(sk);
  	return err;
  }
  
  static int rfcomm_sock_getsockopt_old(struct socket *sock, int optname, char __user *optval, int __user *optlen)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
704
705
  {
  	struct sock *sk = sock->sk;
60c7a3c9c   Marcel Holtmann   Bluetooth: Fix is...
706
707
  	struct sock *l2cap_sk;
  	struct l2cap_conn *conn;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
708
709
  	struct rfcomm_conninfo cinfo;
  	int len, err = 0;
9f2c8a03f   Marcel Holtmann   Bluetooth: Replac...
710
  	u32 opt;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
711
712
713
714
715
716
717
718
719
720
  
  	BT_DBG("sk %p", sk);
  
  	if (get_user(len, optlen))
  		return -EFAULT;
  
  	lock_sock(sk);
  
  	switch (optname) {
  	case RFCOMM_LM:
9f2c8a03f   Marcel Holtmann   Bluetooth: Replac...
721
722
723
724
725
726
727
728
729
  		switch (rfcomm_pi(sk)->sec_level) {
  		case BT_SECURITY_LOW:
  			opt = RFCOMM_LM_AUTH;
  			break;
  		case BT_SECURITY_MEDIUM:
  			opt = RFCOMM_LM_AUTH | RFCOMM_LM_ENCRYPT;
  			break;
  		case BT_SECURITY_HIGH:
  			opt = RFCOMM_LM_AUTH | RFCOMM_LM_ENCRYPT |
2c068e0b9   Marcel Holtmann   Bluetooth: Handle...
730
731
732
733
734
  			      RFCOMM_LM_SECURE;
  			break;
  		case BT_SECURITY_FIPS:
  			opt = RFCOMM_LM_AUTH | RFCOMM_LM_ENCRYPT |
  			      RFCOMM_LM_SECURE | RFCOMM_LM_FIPS;
9f2c8a03f   Marcel Holtmann   Bluetooth: Replac...
735
736
737
738
739
740
741
742
743
744
  			break;
  		default:
  			opt = 0;
  			break;
  		}
  
  		if (rfcomm_pi(sk)->role_switch)
  			opt |= RFCOMM_LM_MASTER;
  
  		if (put_user(opt, (u32 __user *) optval))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
745
  			err = -EFAULT;
2c068e0b9   Marcel Holtmann   Bluetooth: Handle...
746

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
747
748
749
  		break;
  
  	case RFCOMM_CONNINFO:
bb23c0ab8   Marcel Holtmann   Bluetooth: Add su...
750
751
  		if (sk->sk_state != BT_CONNECTED &&
  					!rfcomm_pi(sk)->dlc->defer_setup) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
752
753
754
  			err = -ENOTCONN;
  			break;
  		}
60c7a3c9c   Marcel Holtmann   Bluetooth: Fix is...
755
756
  		l2cap_sk = rfcomm_pi(sk)->dlc->session->sock->sk;
  		conn = l2cap_pi(l2cap_sk)->chan->conn;
8d03e971c   Filip Palian   Bluetooth: l2cap ...
757
  		memset(&cinfo, 0, sizeof(cinfo));
8c1d787be   Gustavo F. Padovan   Bluetooth: Move c...
758
759
  		cinfo.hci_handle = conn->hcon->handle;
  		memcpy(cinfo.dev_class, conn->hcon->dev_class, 3);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
760
761
762
763
764
765
766
767
768
769
770
771
772
  
  		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);
d58daf42d   Marcel Holtmann   Bluetooth: Prepar...
773
774
775
776
777
778
  	return err;
  }
  
  static int rfcomm_sock_getsockopt(struct socket *sock, int level, int optname, char __user *optval, int __user *optlen)
  {
  	struct sock *sk = sock->sk;
9f2c8a03f   Marcel Holtmann   Bluetooth: Replac...
779
  	struct bt_security sec;
d58daf42d   Marcel Holtmann   Bluetooth: Prepar...
780
781
782
783
784
785
  	int len, err = 0;
  
  	BT_DBG("sk %p", sk);
  
  	if (level == SOL_RFCOMM)
  		return rfcomm_sock_getsockopt_old(sock, optname, optval, optlen);
0588d94fd   Marcel Holtmann   Bluetooth: Restri...
786
787
  	if (level != SOL_BLUETOOTH)
  		return -ENOPROTOOPT;
d58daf42d   Marcel Holtmann   Bluetooth: Prepar...
788
789
790
791
792
793
  	if (get_user(len, optlen))
  		return -EFAULT;
  
  	lock_sock(sk);
  
  	switch (optname) {
9f2c8a03f   Marcel Holtmann   Bluetooth: Replac...
794
  	case BT_SECURITY:
0588d94fd   Marcel Holtmann   Bluetooth: Restri...
795
796
797
798
  		if (sk->sk_type != SOCK_STREAM) {
  			err = -EINVAL;
  			break;
  		}
9f2c8a03f   Marcel Holtmann   Bluetooth: Replac...
799
  		sec.level = rfcomm_pi(sk)->sec_level;
9ad2de43f   Mathias Krause   Bluetooth: RFCOMM...
800
  		sec.key_size = 0;
9f2c8a03f   Marcel Holtmann   Bluetooth: Replac...
801
802
803
804
805
806
  
  		len = min_t(unsigned int, len, sizeof(sec));
  		if (copy_to_user(optval, (char *) &sec, len))
  			err = -EFAULT;
  
  		break;
bb23c0ab8   Marcel Holtmann   Bluetooth: Add su...
807
808
809
810
811
  	case BT_DEFER_SETUP:
  		if (sk->sk_state != BT_BOUND && sk->sk_state != BT_LISTEN) {
  			err = -EINVAL;
  			break;
  		}
c5daa683f   Gustavo Padovan   Bluetooth: Create...
812
813
  		if (put_user(test_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags),
  			     (u32 __user *) optval))
bb23c0ab8   Marcel Holtmann   Bluetooth: Add su...
814
815
816
  			err = -EFAULT;
  
  		break;
d58daf42d   Marcel Holtmann   Bluetooth: Prepar...
817
818
819
820
821
822
  	default:
  		err = -ENOPROTOOPT;
  		break;
  	}
  
  	release_sock(sk);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
823
824
825
826
827
  	return err;
  }
  
  static int rfcomm_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
  {
e19caae71   David S. Miller   bluetooth: Fix un...
828
  	struct sock *sk __maybe_unused = sock->sk;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
829
  	int err;
e19caae71   David S. Miller   bluetooth: Fix un...
830
  	BT_DBG("sk %p cmd %x arg %lx", sk, cmd, arg);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
831

3241ad820   Marcel Holtmann   [Bluetooth] Add t...
832
  	err = bt_sock_ioctl(sock, cmd, arg);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
833

3241ad820   Marcel Holtmann   [Bluetooth] Add t...
834
  	if (err == -ENOIOCTLCMD) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
835
  #ifdef CONFIG_BT_RFCOMM_TTY
3241ad820   Marcel Holtmann   [Bluetooth] Add t...
836
837
838
  		lock_sock(sk);
  		err = rfcomm_dev_ioctl(sk, cmd, (void __user *) arg);
  		release_sock(sk);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
839
  #else
3241ad820   Marcel Holtmann   [Bluetooth] Add t...
840
  		err = -EOPNOTSUPP;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
841
  #endif
3241ad820   Marcel Holtmann   [Bluetooth] Add t...
842
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
843

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
844
845
846
847
848
849
850
851
852
  	return err;
  }
  
  static int rfcomm_sock_shutdown(struct socket *sock, int how)
  {
  	struct sock *sk = sock->sk;
  	int err = 0;
  
  	BT_DBG("sock %p, sk %p", sock, sk);
285b4e903   Andrei Emeltchenko   Bluetooth: clean ...
853
854
  	if (!sk)
  		return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
855
856
857
858
859
  
  	lock_sock(sk);
  	if (!sk->sk_shutdown) {
  		sk->sk_shutdown = SHUTDOWN_MASK;
  		__rfcomm_sock_close(sk);
093facf36   Vladimir Davydov   Bluetooth: never ...
860
861
  		if (sock_flag(sk, SOCK_LINGER) && sk->sk_lingertime &&
  		    !(current->flags & PF_EXITING))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
  			err = bt_sock_wait_state(sk, BT_CLOSED, sk->sk_lingertime);
  	}
  	release_sock(sk);
  	return err;
  }
  
  static int rfcomm_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 = rfcomm_sock_shutdown(sock, 2);
  
  	sock_orphan(sk);
  	rfcomm_sock_kill(sk);
  	return err;
  }
8e87d1425   YOSHIFUJI Hideaki   [NET] BLUETOOTH: ...
884
  /* ---- RFCOMM core layer callbacks ----
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
   *
   * called under rfcomm_lock()
   */
  int rfcomm_connect_ind(struct rfcomm_session *s, u8 channel, struct rfcomm_dlc **d)
  {
  	struct sock *sk, *parent;
  	bdaddr_t src, dst;
  	int result = 0;
  
  	BT_DBG("session %p channel %d", s, channel);
  
  	rfcomm_session_getaddr(s, &src, &dst);
  
  	/* Check if we have socket listening on channel */
  	parent = rfcomm_get_sock_by_channel(BT_LISTEN, channel, &src);
  	if (!parent)
  		return 0;
eeb366564   Gustavo F. Padovan   Bluetooth: Get ri...
902
  	bh_lock_sock(parent);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
903
904
  	/* Check for backlog size */
  	if (sk_acceptq_is_full(parent)) {
8e87d1425   YOSHIFUJI Hideaki   [NET] BLUETOOTH: ...
905
  		BT_DBG("backlog full %d", parent->sk_ack_backlog);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
906
907
  		goto done;
  	}
11aa9c28b   Eric W. Biederman   net: Pass kern fr...
908
  	sk = rfcomm_sock_alloc(sock_net(parent), NULL, BTPROTO_RFCOMM, GFP_ATOMIC, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
909
910
  	if (!sk)
  		goto done;
b5a30dda6   Octavian Purdila   Bluetooth: silenc...
911
  	bt_sock_reclassify_lock(sk, BTPROTO_RFCOMM);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
912
  	rfcomm_sock_init(sk, parent);
94a86df01   Marcel Holtmann   Bluetooth: Store ...
913
914
  	bacpy(&rfcomm_pi(sk)->src, &src);
  	bacpy(&rfcomm_pi(sk)->dst, &dst);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
915
916
917
918
919
920
921
922
923
924
925
  	rfcomm_pi(sk)->channel = channel;
  
  	sk->sk_state = BT_CONFIG;
  	bt_accept_enqueue(parent, sk);
  
  	/* Accept connection and return socket DLC */
  	*d = rfcomm_pi(sk)->dlc;
  	result = 1;
  
  done:
  	bh_unlock_sock(parent);
bb23c0ab8   Marcel Holtmann   Bluetooth: Add su...
926

c5daa683f   Gustavo Padovan   Bluetooth: Create...
927
  	if (test_bit(BT_SK_DEFER_SETUP, &bt_sk(parent)->flags))
bb23c0ab8   Marcel Holtmann   Bluetooth: Add su...
928
  		parent->sk_state_change(parent);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
929
930
  	return result;
  }
aef7d97cc   Marcel Holtmann   Bluetooth: Conver...
931
  static int rfcomm_sock_debugfs_show(struct seq_file *f, void *p)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
932
933
  {
  	struct sock *sk;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
934

95ca83f42   Gustavo F. Padovan   Bluetooth: Fix co...
935
  	read_lock(&rfcomm_sk_list.lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
936

b67bfe0d4   Sasha Levin   hlist: drop the n...
937
  	sk_for_each(sk, &rfcomm_sk_list.head) {
fcb73338e   Andrei Emeltchenko   Bluetooth: Use %p...
938
939
  		seq_printf(f, "%pMR %pMR %d %d
  ",
94a86df01   Marcel Holtmann   Bluetooth: Store ...
940
  			   &rfcomm_pi(sk)->src, &rfcomm_pi(sk)->dst,
fcb73338e   Andrei Emeltchenko   Bluetooth: Use %p...
941
  			   sk->sk_state, rfcomm_pi(sk)->channel);
be9d12273   Marcel Holtmann   [Bluetooth]: Remo...
942
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
943

95ca83f42   Gustavo F. Padovan   Bluetooth: Fix co...
944
  	read_unlock(&rfcomm_sk_list.lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
945

aef7d97cc   Marcel Holtmann   Bluetooth: Conver...
946
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
947
  }
aef7d97cc   Marcel Holtmann   Bluetooth: Conver...
948
949
950
951
952
953
954
955
956
957
958
959
960
  static int rfcomm_sock_debugfs_open(struct inode *inode, struct file *file)
  {
  	return single_open(file, rfcomm_sock_debugfs_show, inode->i_private);
  }
  
  static const struct file_operations rfcomm_sock_debugfs_fops = {
  	.open		= rfcomm_sock_debugfs_open,
  	.read		= seq_read,
  	.llseek		= seq_lseek,
  	.release	= single_release,
  };
  
  static struct dentry *rfcomm_sock_debugfs;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
961

90ddc4f04   Eric Dumazet   [NET]: move struc...
962
  static const struct proto_ops rfcomm_sock_ops = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
  	.family		= PF_BLUETOOTH,
  	.owner		= THIS_MODULE,
  	.release	= rfcomm_sock_release,
  	.bind		= rfcomm_sock_bind,
  	.connect	= rfcomm_sock_connect,
  	.listen		= rfcomm_sock_listen,
  	.accept		= rfcomm_sock_accept,
  	.getname	= rfcomm_sock_getname,
  	.sendmsg	= rfcomm_sock_sendmsg,
  	.recvmsg	= rfcomm_sock_recvmsg,
  	.shutdown	= rfcomm_sock_shutdown,
  	.setsockopt	= rfcomm_sock_setsockopt,
  	.getsockopt	= rfcomm_sock_getsockopt,
  	.ioctl		= rfcomm_sock_ioctl,
  	.poll		= bt_sock_poll,
  	.socketpair	= sock_no_socketpair,
  	.mmap		= sock_no_mmap
  };
ec1b4cf74   Stephen Hemminger   net: mark net_pro...
981
  static const struct net_proto_family rfcomm_sock_family_ops = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
982
983
984
985
  	.family		= PF_BLUETOOTH,
  	.owner		= THIS_MODULE,
  	.create		= rfcomm_sock_create
  };
be9d12273   Marcel Holtmann   [Bluetooth]: Remo...
986
  int __init rfcomm_init_sockets(void)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
987
988
  {
  	int err;
74b3fb8d0   Marcel Holtmann   Bluetooth: Add BU...
989
  	BUILD_BUG_ON(sizeof(struct sockaddr_rc) > sizeof(struct sockaddr));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
990
991
992
993
994
  	err = proto_register(&rfcomm_proto, 0);
  	if (err < 0)
  		return err;
  
  	err = bt_sock_register(BTPROTO_RFCOMM, &rfcomm_sock_family_ops);
c6f5df16a   Masatake YAMATO   Bluetooth: Added ...
995
996
997
998
  	if (err < 0) {
  		BT_ERR("RFCOMM socket layer registration failed");
  		goto error;
  	}
b03166152   Al Viro   bluetooth: kill u...
999
  	err = bt_procfs_init(&init_net, "rfcomm", &rfcomm_sk_list, NULL);
c6f5df16a   Masatake YAMATO   Bluetooth: Added ...
1000
1001
1002
  	if (err < 0) {
  		BT_ERR("Failed to create RFCOMM proc file");
  		bt_sock_unregister(BTPROTO_RFCOMM);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1003
  		goto error;
c6f5df16a   Masatake YAMATO   Bluetooth: Added ...
1004
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1005

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1006
  	BT_INFO("RFCOMM socket layer initialized");
1120e4bfa   Marcel Holtmann   Bluetooth: Use IS...
1007
1008
1009
1010
1011
1012
  	if (IS_ERR_OR_NULL(bt_debugfs))
  		return 0;
  
  	rfcomm_sock_debugfs = debugfs_create_file("rfcomm", 0444,
  						  bt_debugfs, NULL,
  						  &rfcomm_sock_debugfs_fops);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1013
1014
1015
  	return 0;
  
  error:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1016
1017
1018
  	proto_unregister(&rfcomm_proto);
  	return err;
  }
2f8362afc   Gustavo F. Padovan   Bluetooth: Add __...
1019
  void __exit rfcomm_cleanup_sockets(void)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1020
  {
c6f5df16a   Masatake YAMATO   Bluetooth: Added ...
1021
  	bt_procfs_cleanup(&init_net, "rfcomm");
aef7d97cc   Marcel Holtmann   Bluetooth: Conver...
1022
  	debugfs_remove(rfcomm_sock_debugfs);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1023

5e9d7f868   David Herrmann   Bluetooth: discar...
1024
  	bt_sock_unregister(BTPROTO_RFCOMM);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1025
1026
1027
  
  	proto_unregister(&rfcomm_proto);
  }