pandora: defconfig: update
[pandora-kernel.git] / net / bluetooth / bnep / sock.c
1 /*
2    BNEP implementation for Linux Bluetooth stack (BlueZ).
3    Copyright (C) 2001-2002 Inventel Systemes
4    Written 2001-2002 by
5         David Libault  <david.libault@inventel.fr>
6
7    Copyright (C) 2002 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 #include <linux/module.h>
28
29 #include <linux/types.h>
30 #include <linux/capability.h>
31 #include <linux/errno.h>
32 #include <linux/kernel.h>
33 #include <linux/poll.h>
34 #include <linux/fcntl.h>
35 #include <linux/skbuff.h>
36 #include <linux/socket.h>
37 #include <linux/ioctl.h>
38 #include <linux/file.h>
39 #include <linux/init.h>
40 #include <linux/compat.h>
41 #include <linux/gfp.h>
42 #include <linux/uaccess.h>
43 #include <net/sock.h>
44
45 #include <asm/system.h>
46
47 #include "bnep.h"
48
49 static int bnep_sock_release(struct socket *sock)
50 {
51         struct sock *sk = sock->sk;
52
53         BT_DBG("sock %p sk %p", sock, sk);
54
55         if (!sk)
56                 return 0;
57
58         sock_orphan(sk);
59         sock_put(sk);
60         return 0;
61 }
62
63 static int bnep_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
64 {
65         struct bnep_connlist_req cl;
66         struct bnep_connadd_req  ca;
67         struct bnep_conndel_req  cd;
68         struct bnep_conninfo ci;
69         struct socket *nsock;
70         void __user *argp = (void __user *)arg;
71         int err;
72
73         BT_DBG("cmd %x arg %lx", cmd, arg);
74
75         switch (cmd) {
76         case BNEPCONNADD:
77                 if (!capable(CAP_NET_ADMIN))
78                         return -EACCES;
79
80                 if (copy_from_user(&ca, argp, sizeof(ca)))
81                         return -EFAULT;
82
83                 nsock = sockfd_lookup(ca.sock, &err);
84                 if (!nsock)
85                         return err;
86
87                 if (nsock->sk->sk_state != BT_CONNECTED) {
88                         sockfd_put(nsock);
89                         return -EBADFD;
90                 }
91                 ca.device[sizeof(ca.device)-1] = 0;
92
93                 err = bnep_add_connection(&ca, nsock);
94                 if (!err) {
95                         if (copy_to_user(argp, &ca, sizeof(ca)))
96                                 err = -EFAULT;
97                 } else
98                         sockfd_put(nsock);
99
100                 return err;
101
102         case BNEPCONNDEL:
103                 if (!capable(CAP_NET_ADMIN))
104                         return -EACCES;
105
106                 if (copy_from_user(&cd, argp, sizeof(cd)))
107                         return -EFAULT;
108
109                 return bnep_del_connection(&cd);
110
111         case BNEPGETCONNLIST:
112                 if (copy_from_user(&cl, argp, sizeof(cl)))
113                         return -EFAULT;
114
115                 if (cl.cnum <= 0)
116                         return -EINVAL;
117
118                 err = bnep_get_connlist(&cl);
119                 if (!err && copy_to_user(argp, &cl, sizeof(cl)))
120                         return -EFAULT;
121
122                 return err;
123
124         case BNEPGETCONNINFO:
125                 if (copy_from_user(&ci, argp, sizeof(ci)))
126                         return -EFAULT;
127
128                 err = bnep_get_conninfo(&ci);
129                 if (!err && copy_to_user(argp, &ci, sizeof(ci)))
130                         return -EFAULT;
131
132                 return err;
133
134         default:
135                 return -EINVAL;
136         }
137
138         return 0;
139 }
140
141 #ifdef CONFIG_COMPAT
142 static int bnep_sock_compat_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
143 {
144         if (cmd == BNEPGETCONNLIST) {
145                 struct bnep_connlist_req cl;
146                 uint32_t uci;
147                 int err;
148
149                 if (get_user(cl.cnum, (uint32_t __user *) arg) ||
150                                 get_user(uci, (u32 __user *) (arg + 4)))
151                         return -EFAULT;
152
153                 cl.ci = compat_ptr(uci);
154
155                 if (cl.cnum <= 0)
156                         return -EINVAL;
157
158                 err = bnep_get_connlist(&cl);
159
160                 if (!err && put_user(cl.cnum, (uint32_t __user *) arg))
161                         err = -EFAULT;
162
163                 return err;
164         }
165
166         return bnep_sock_ioctl(sock, cmd, arg);
167 }
168 #endif
169
170 static const struct proto_ops bnep_sock_ops = {
171         .family         = PF_BLUETOOTH,
172         .owner          = THIS_MODULE,
173         .release        = bnep_sock_release,
174         .ioctl          = bnep_sock_ioctl,
175 #ifdef CONFIG_COMPAT
176         .compat_ioctl   = bnep_sock_compat_ioctl,
177 #endif
178         .bind           = sock_no_bind,
179         .getname        = sock_no_getname,
180         .sendmsg        = sock_no_sendmsg,
181         .recvmsg        = sock_no_recvmsg,
182         .poll           = sock_no_poll,
183         .listen         = sock_no_listen,
184         .shutdown       = sock_no_shutdown,
185         .setsockopt     = sock_no_setsockopt,
186         .getsockopt     = sock_no_getsockopt,
187         .connect        = sock_no_connect,
188         .socketpair     = sock_no_socketpair,
189         .accept         = sock_no_accept,
190         .mmap           = sock_no_mmap
191 };
192
193 static struct proto bnep_proto = {
194         .name           = "BNEP",
195         .owner          = THIS_MODULE,
196         .obj_size       = sizeof(struct bt_sock)
197 };
198
199 static int bnep_sock_create(struct net *net, struct socket *sock, int protocol,
200                             int kern)
201 {
202         struct sock *sk;
203
204         BT_DBG("sock %p", sock);
205
206         if (sock->type != SOCK_RAW)
207                 return -ESOCKTNOSUPPORT;
208
209         sk = sk_alloc(net, PF_BLUETOOTH, GFP_ATOMIC, &bnep_proto);
210         if (!sk)
211                 return -ENOMEM;
212
213         sock_init_data(sock, sk);
214
215         sock->ops = &bnep_sock_ops;
216
217         sock->state = SS_UNCONNECTED;
218
219         sock_reset_flag(sk, SOCK_ZAPPED);
220
221         sk->sk_protocol = protocol;
222         sk->sk_state    = BT_OPEN;
223
224         return 0;
225 }
226
227 static const struct net_proto_family bnep_sock_family_ops = {
228         .family = PF_BLUETOOTH,
229         .owner  = THIS_MODULE,
230         .create = bnep_sock_create
231 };
232
233 int __init bnep_sock_init(void)
234 {
235         int err;
236
237         err = proto_register(&bnep_proto, 0);
238         if (err < 0)
239                 return err;
240
241         err = bt_sock_register(BTPROTO_BNEP, &bnep_sock_family_ops);
242         if (err < 0)
243                 goto error;
244
245         return 0;
246
247 error:
248         BT_ERR("Can't register BNEP socket");
249         proto_unregister(&bnep_proto);
250         return err;
251 }
252
253 void __exit bnep_sock_cleanup(void)
254 {
255         if (bt_sock_unregister(BTPROTO_BNEP) < 0)
256                 BT_ERR("Can't unregister BNEP socket");
257
258         proto_unregister(&bnep_proto);
259 }