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