Bluetooth: move l2cap_sock_release() to l2cap_sock.c
[deliverable/linux.git] / net / bluetooth / l2cap_sock.c
CommitLineData
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
32static 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
65static 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
82static 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
90void 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
138static struct proto l2cap_proto = {
139 .name = "L2CAP",
140 .owner = THIS_MODULE,
141 .obj_size = sizeof(struct l2cap_pinfo)
142};
143
144struct 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
169static 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
195const 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
215static const struct net_proto_family l2cap_sock_family_ops = {
216 .family = PF_BLUETOOTH,
217 .owner = THIS_MODULE,
218 .create = l2cap_sock_create,
219};
220
221int __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
237error:
238 BT_ERR("L2CAP socket registration failed");
239 proto_unregister(&l2cap_proto);
240 return err;
241}
242
243void 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}
This page took 0.031772 seconds and 5 git commands to generate.