]> git.kernelconcepts.de Git - karo-tx-linux.git/blob - net/bluetooth/cmtp/sock.c
84345d4e3c18e38e41b4504bd23ba1da913c09d1
[karo-tx-linux.git] / net / bluetooth / cmtp / sock.c
1 /* 
2    CMTP implementation for Linux Bluetooth stack (BlueZ).
3    Copyright (C) 2002-2003 Marcel Holtmann <marcel@holtmann.org>
4
5    This program is free software; you can redistribute it and/or modify
6    it under the terms of the GNU General Public License version 2 as
7    published by the Free Software Foundation;
8
9    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
10    OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
11    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
12    IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
13    CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES 
14    WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 
15    ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 
16    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17
18    ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS, 
19    COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS 
20    SOFTWARE IS DISCLAIMED.
21 */
22
23 #include <linux/config.h>
24 #include <linux/module.h>
25
26 #include <linux/types.h>
27 #include <linux/capability.h>
28 #include <linux/errno.h>
29 #include <linux/kernel.h>
30 #include <linux/sched.h>
31 #include <linux/slab.h>
32 #include <linux/poll.h>
33 #include <linux/fcntl.h>
34 #include <linux/skbuff.h>
35 #include <linux/socket.h>
36 #include <linux/ioctl.h>
37 #include <linux/file.h>
38 #include <linux/compat.h>
39 #include <net/sock.h>
40
41 #include <linux/isdn/capilli.h>
42
43 #include <asm/system.h>
44 #include <asm/uaccess.h>
45
46 #include "cmtp.h"
47
48 #ifndef CONFIG_BT_CMTP_DEBUG
49 #undef  BT_DBG
50 #define BT_DBG(D...)
51 #endif
52
53 static int cmtp_sock_release(struct socket *sock)
54 {
55         struct sock *sk = sock->sk;
56
57         BT_DBG("sock %p sk %p", sock, sk);
58
59         if (!sk)
60                 return 0;
61
62         sock_orphan(sk);
63         sock_put(sk);
64
65         return 0;
66 }
67
68 static int cmtp_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
69 {
70         struct cmtp_connadd_req ca;
71         struct cmtp_conndel_req cd;
72         struct cmtp_connlist_req cl;
73         struct cmtp_conninfo ci;
74         struct socket *nsock;
75         void __user *argp = (void __user *)arg;
76         int err;
77
78         BT_DBG("cmd %x arg %lx", cmd, arg);
79
80         switch (cmd) {
81         case CMTPCONNADD:
82                 if (!capable(CAP_NET_ADMIN))
83                         return -EACCES;
84
85                 if (copy_from_user(&ca, argp, sizeof(ca)))
86                         return -EFAULT;
87
88                 nsock = sockfd_lookup(ca.sock, &err);
89                 if (!nsock)
90                         return err;
91
92                 if (nsock->sk->sk_state != BT_CONNECTED) {
93                         fput(nsock->file);
94                         return -EBADFD;
95                 }
96
97                 err = cmtp_add_connection(&ca, nsock);
98                 if (!err) {
99                         if (copy_to_user(argp, &ca, sizeof(ca)))
100                                 err = -EFAULT;
101                 } else
102                         fput(nsock->file);
103
104                 return err;
105
106         case CMTPCONNDEL:
107                 if (!capable(CAP_NET_ADMIN))
108                         return -EACCES;
109
110                 if (copy_from_user(&cd, argp, sizeof(cd)))
111                         return -EFAULT;
112
113                 return cmtp_del_connection(&cd);
114
115         case CMTPGETCONNLIST:
116                 if (copy_from_user(&cl, argp, sizeof(cl)))
117                         return -EFAULT;
118
119                 if (cl.cnum <= 0)
120                         return -EINVAL;
121
122                 err = cmtp_get_connlist(&cl);
123                 if (!err && copy_to_user(argp, &cl, sizeof(cl)))
124                         return -EFAULT;
125
126                 return err;
127
128         case CMTPGETCONNINFO:
129                 if (copy_from_user(&ci, argp, sizeof(ci)))
130                         return -EFAULT;
131
132                 err = cmtp_get_conninfo(&ci);
133                 if (!err && copy_to_user(argp, &ci, sizeof(ci)))
134                         return -EFAULT;
135
136                 return err;
137         }
138
139         return -EINVAL;
140 }
141
142 #ifdef CONFIG_COMPAT
143 static int cmtp_sock_compat_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
144 {
145         if (cmd == CMTPGETCONNLIST) {
146                 struct cmtp_connlist_req cl;
147                 uint32_t uci;
148                 int err;
149
150                 if (get_user(cl.cnum, (uint32_t __user *) arg) ||
151                                 get_user(uci, (u32 __user *) (arg + 4)))
152                         return -EFAULT;
153
154                 cl.ci = compat_ptr(uci);
155
156                 if (cl.cnum <= 0)
157                         return -EINVAL;
158         
159                 err = cmtp_get_connlist(&cl);
160
161                 if (!err && put_user(cl.cnum, (uint32_t __user *) arg))
162                         err = -EFAULT;
163
164                 return err;
165         }
166
167         return cmtp_sock_ioctl(sock, cmd, arg);
168 }
169 #endif
170
171 static const struct proto_ops cmtp_sock_ops = {
172         .family         = PF_BLUETOOTH,
173         .owner          = THIS_MODULE,
174         .release        = cmtp_sock_release,
175         .ioctl          = cmtp_sock_ioctl,
176 #ifdef CONFIG_COMPAT
177         .compat_ioctl   = cmtp_sock_compat_ioctl,
178 #endif
179         .bind           = sock_no_bind,
180         .getname        = sock_no_getname,
181         .sendmsg        = sock_no_sendmsg,
182         .recvmsg        = sock_no_recvmsg,
183         .poll           = sock_no_poll,
184         .listen         = sock_no_listen,
185         .shutdown       = sock_no_shutdown,
186         .setsockopt     = sock_no_setsockopt,
187         .getsockopt     = sock_no_getsockopt,
188         .connect        = sock_no_connect,
189         .socketpair     = sock_no_socketpair,
190         .accept         = sock_no_accept,
191         .mmap           = sock_no_mmap
192 };
193
194 static struct proto cmtp_proto = {
195         .name           = "CMTP",
196         .owner          = THIS_MODULE,
197         .obj_size       = sizeof(struct bt_sock)
198 };
199
200 static int cmtp_sock_create(struct socket *sock, int protocol)
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(PF_BLUETOOTH, GFP_KERNEL, &cmtp_proto, 1);
210         if (!sk)
211                 return -ENOMEM;
212
213         sock_init_data(sock, sk);
214
215         sock->ops = &cmtp_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 struct net_proto_family cmtp_sock_family_ops = {
228         .family = PF_BLUETOOTH,
229         .owner  = THIS_MODULE,
230         .create = cmtp_sock_create
231 };
232
233 int cmtp_init_sockets(void)
234 {
235         int err;
236
237         err = proto_register(&cmtp_proto, 0);
238         if (err < 0)
239                 return err;
240
241         err = bt_sock_register(BTPROTO_CMTP, &cmtp_sock_family_ops);
242         if (err < 0)
243                 goto error;
244
245         return 0;
246
247 error:
248         BT_ERR("Can't register CMTP socket");
249         proto_unregister(&cmtp_proto);
250         return err;
251 }
252
253 void cmtp_cleanup_sockets(void)
254 {
255         if (bt_sock_unregister(BTPROTO_CMTP) < 0)
256                 BT_ERR("Can't unregister CMTP socket");
257
258         proto_unregister(&cmtp_proto);
259 }