checkpatch: improve GIT_COMMIT_ID test
[linux-2.6-microblaze.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/export.h>
28 #include <linux/file.h>
29
30 #include "bnep.h"
31
32 static struct bt_sock_list bnep_sk_list = {
33         .lock = __RW_LOCK_UNLOCKED(bnep_sk_list.lock)
34 };
35
36 static int bnep_sock_release(struct socket *sock)
37 {
38         struct sock *sk = sock->sk;
39
40         BT_DBG("sock %p sk %p", sock, sk);
41
42         if (!sk)
43                 return 0;
44
45         bt_sock_unlink(&bnep_sk_list, sk);
46
47         sock_orphan(sk);
48         sock_put(sk);
49         return 0;
50 }
51
52 static int do_bnep_sock_ioctl(struct socket *sock, unsigned int cmd, void __user *argp)
53 {
54         struct bnep_connlist_req cl;
55         struct bnep_connadd_req  ca;
56         struct bnep_conndel_req  cd;
57         struct bnep_conninfo ci;
58         struct socket *nsock;
59         __u32 supp_feat = BIT(BNEP_SETUP_RESPONSE);
60         int err;
61
62         BT_DBG("cmd %x arg %p", cmd, argp);
63
64         switch (cmd) {
65         case BNEPCONNADD:
66                 if (!capable(CAP_NET_ADMIN))
67                         return -EPERM;
68
69                 if (copy_from_user(&ca, argp, sizeof(ca)))
70                         return -EFAULT;
71
72                 nsock = sockfd_lookup(ca.sock, &err);
73                 if (!nsock)
74                         return err;
75
76                 if (nsock->sk->sk_state != BT_CONNECTED) {
77                         sockfd_put(nsock);
78                         return -EBADFD;
79                 }
80                 ca.device[sizeof(ca.device)-1] = 0;
81
82                 err = bnep_add_connection(&ca, nsock);
83                 if (!err) {
84                         if (copy_to_user(argp, &ca, sizeof(ca)))
85                                 err = -EFAULT;
86                 } else
87                         sockfd_put(nsock);
88
89                 return err;
90
91         case BNEPCONNDEL:
92                 if (!capable(CAP_NET_ADMIN))
93                         return -EPERM;
94
95                 if (copy_from_user(&cd, argp, sizeof(cd)))
96                         return -EFAULT;
97
98                 return bnep_del_connection(&cd);
99
100         case BNEPGETCONNLIST:
101                 if (copy_from_user(&cl, argp, sizeof(cl)))
102                         return -EFAULT;
103
104                 if (cl.cnum <= 0)
105                         return -EINVAL;
106
107                 err = bnep_get_connlist(&cl);
108                 if (!err && copy_to_user(argp, &cl, sizeof(cl)))
109                         return -EFAULT;
110
111                 return err;
112
113         case BNEPGETCONNINFO:
114                 if (copy_from_user(&ci, argp, sizeof(ci)))
115                         return -EFAULT;
116
117                 err = bnep_get_conninfo(&ci);
118                 if (!err && copy_to_user(argp, &ci, sizeof(ci)))
119                         return -EFAULT;
120
121                 return err;
122
123         case BNEPGETSUPPFEAT:
124                 if (copy_to_user(argp, &supp_feat, sizeof(supp_feat)))
125                         return -EFAULT;
126
127                 return 0;
128
129         default:
130                 return -EINVAL;
131         }
132
133         return 0;
134 }
135
136 static int bnep_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
137 {
138         return do_bnep_sock_ioctl(sock, cmd, (void __user *)arg);
139 }
140
141 #ifdef CONFIG_COMPAT
142 static int bnep_sock_compat_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
143 {
144         void __user *argp = compat_ptr(arg);
145         if (cmd == BNEPGETCONNLIST) {
146                 struct bnep_connlist_req cl;
147                 unsigned __user *p = argp;
148                 u32 uci;
149                 int err;
150
151                 if (get_user(cl.cnum, p) || get_user(uci, p + 1))
152                         return -EFAULT;
153
154                 cl.ci = compat_ptr(uci);
155
156                 if (cl.cnum <= 0)
157                         return -EINVAL;
158
159                 err = bnep_get_connlist(&cl);
160
161                 if (!err && put_user(cl.cnum, p))
162                         err = -EFAULT;
163
164                 return err;
165         }
166
167         return do_bnep_sock_ioctl(sock, cmd, argp);
168 }
169 #endif
170
171 static const struct proto_ops bnep_sock_ops = {
172         .family         = PF_BLUETOOTH,
173         .owner          = THIS_MODULE,
174         .release        = bnep_sock_release,
175         .ioctl          = bnep_sock_ioctl,
176 #ifdef CONFIG_COMPAT
177         .compat_ioctl   = bnep_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         .listen         = sock_no_listen,
184         .shutdown       = sock_no_shutdown,
185         .connect        = sock_no_connect,
186         .socketpair     = sock_no_socketpair,
187         .accept         = sock_no_accept,
188         .mmap           = sock_no_mmap
189 };
190
191 static struct proto bnep_proto = {
192         .name           = "BNEP",
193         .owner          = THIS_MODULE,
194         .obj_size       = sizeof(struct bt_sock)
195 };
196
197 static int bnep_sock_create(struct net *net, struct socket *sock, int protocol,
198                             int kern)
199 {
200         struct sock *sk;
201
202         BT_DBG("sock %p", sock);
203
204         if (sock->type != SOCK_RAW)
205                 return -ESOCKTNOSUPPORT;
206
207         sk = sk_alloc(net, PF_BLUETOOTH, GFP_ATOMIC, &bnep_proto, kern);
208         if (!sk)
209                 return -ENOMEM;
210
211         sock_init_data(sock, sk);
212
213         sock->ops = &bnep_sock_ops;
214
215         sock->state = SS_UNCONNECTED;
216
217         sock_reset_flag(sk, SOCK_ZAPPED);
218
219         sk->sk_protocol = protocol;
220         sk->sk_state    = BT_OPEN;
221
222         bt_sock_link(&bnep_sk_list, sk);
223         return 0;
224 }
225
226 static const struct net_proto_family bnep_sock_family_ops = {
227         .family = PF_BLUETOOTH,
228         .owner  = THIS_MODULE,
229         .create = bnep_sock_create
230 };
231
232 int __init bnep_sock_init(void)
233 {
234         int err;
235
236         err = proto_register(&bnep_proto, 0);
237         if (err < 0)
238                 return err;
239
240         err = bt_sock_register(BTPROTO_BNEP, &bnep_sock_family_ops);
241         if (err < 0) {
242                 BT_ERR("Can't register BNEP socket");
243                 goto error;
244         }
245
246         err = bt_procfs_init(&init_net, "bnep", &bnep_sk_list, NULL);
247         if (err < 0) {
248                 BT_ERR("Failed to create BNEP proc file");
249                 bt_sock_unregister(BTPROTO_BNEP);
250                 goto error;
251         }
252
253         BT_INFO("BNEP socket layer initialized");
254
255         return 0;
256
257 error:
258         proto_unregister(&bnep_proto);
259         return err;
260 }
261
262 void __exit bnep_sock_cleanup(void)
263 {
264         bt_procfs_cleanup(&init_net, "bnep");
265         bt_sock_unregister(BTPROTO_BNEP);
266         proto_unregister(&bnep_proto);
267 }