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