xref: /openbmc/linux/net/bluetooth/cmtp/sock.c (revision 0c874100)
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/export.h>
24 
25 #include <linux/types.h>
26 #include <linux/capability.h>
27 #include <linux/errno.h>
28 #include <linux/kernel.h>
29 #include <linux/poll.h>
30 #include <linux/fcntl.h>
31 #include <linux/skbuff.h>
32 #include <linux/socket.h>
33 #include <linux/ioctl.h>
34 #include <linux/file.h>
35 #include <linux/compat.h>
36 #include <linux/gfp.h>
37 #include <linux/uaccess.h>
38 #include <net/sock.h>
39 
40 #include <linux/isdn/capilli.h>
41 
42 
43 #include "cmtp.h"
44 
45 static struct bt_sock_list cmtp_sk_list = {
46 	.lock = __RW_LOCK_UNLOCKED(cmtp_sk_list.lock)
47 };
48 
49 static int cmtp_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 	bt_sock_unlink(&cmtp_sk_list, sk);
59 
60 	sock_orphan(sk);
61 	sock_put(sk);
62 
63 	return 0;
64 }
65 
66 static int do_cmtp_sock_ioctl(struct socket *sock, unsigned int cmd, void __user *argp)
67 {
68 	struct cmtp_connadd_req ca;
69 	struct cmtp_conndel_req cd;
70 	struct cmtp_connlist_req cl;
71 	struct cmtp_conninfo ci;
72 	struct socket *nsock;
73 	int err;
74 
75 	BT_DBG("cmd %x arg %p", cmd, argp);
76 
77 	switch (cmd) {
78 	case CMTPCONNADD:
79 		if (!capable(CAP_NET_ADMIN))
80 			return -EPERM;
81 
82 		if (copy_from_user(&ca, argp, sizeof(ca)))
83 			return -EFAULT;
84 
85 		nsock = sockfd_lookup(ca.sock, &err);
86 		if (!nsock)
87 			return err;
88 
89 		if (nsock->sk->sk_state != BT_CONNECTED) {
90 			sockfd_put(nsock);
91 			return -EBADFD;
92 		}
93 
94 		err = cmtp_add_connection(&ca, nsock);
95 		if (!err) {
96 			if (copy_to_user(argp, &ca, sizeof(ca)))
97 				err = -EFAULT;
98 		} else
99 			sockfd_put(nsock);
100 
101 		return err;
102 
103 	case CMTPCONNDEL:
104 		if (!capable(CAP_NET_ADMIN))
105 			return -EPERM;
106 
107 		if (copy_from_user(&cd, argp, sizeof(cd)))
108 			return -EFAULT;
109 
110 		return cmtp_del_connection(&cd);
111 
112 	case CMTPGETCONNLIST:
113 		if (copy_from_user(&cl, argp, sizeof(cl)))
114 			return -EFAULT;
115 
116 		if (cl.cnum <= 0)
117 			return -EINVAL;
118 
119 		err = cmtp_get_connlist(&cl);
120 		if (!err && copy_to_user(argp, &cl, sizeof(cl)))
121 			return -EFAULT;
122 
123 		return err;
124 
125 	case CMTPGETCONNINFO:
126 		if (copy_from_user(&ci, argp, sizeof(ci)))
127 			return -EFAULT;
128 
129 		err = cmtp_get_conninfo(&ci);
130 		if (!err && copy_to_user(argp, &ci, sizeof(ci)))
131 			return -EFAULT;
132 
133 		return err;
134 	}
135 
136 	return -EINVAL;
137 }
138 
139 static int cmtp_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
140 {
141 	return do_cmtp_sock_ioctl(sock, cmd, (void __user *)arg);
142 }
143 
144 #ifdef CONFIG_COMPAT
145 static int cmtp_sock_compat_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
146 {
147 	void __user *argp = compat_ptr(arg);
148 	if (cmd == CMTPGETCONNLIST) {
149 		struct cmtp_connlist_req cl;
150 		u32 __user *p = argp;
151 		u32 uci;
152 		int err;
153 
154 		if (get_user(cl.cnum, p) || get_user(uci, p + 1))
155 			return -EFAULT;
156 
157 		cl.ci = compat_ptr(uci);
158 
159 		if (cl.cnum <= 0)
160 			return -EINVAL;
161 
162 		err = cmtp_get_connlist(&cl);
163 
164 		if (!err && put_user(cl.cnum, p))
165 			err = -EFAULT;
166 
167 		return err;
168 	}
169 
170 	return do_cmtp_sock_ioctl(sock, cmd, argp);
171 }
172 #endif
173 
174 static const struct proto_ops cmtp_sock_ops = {
175 	.family		= PF_BLUETOOTH,
176 	.owner		= THIS_MODULE,
177 	.release	= cmtp_sock_release,
178 	.ioctl		= cmtp_sock_ioctl,
179 #ifdef CONFIG_COMPAT
180 	.compat_ioctl	= cmtp_sock_compat_ioctl,
181 #endif
182 	.bind		= sock_no_bind,
183 	.getname	= sock_no_getname,
184 	.sendmsg	= sock_no_sendmsg,
185 	.recvmsg	= sock_no_recvmsg,
186 	.listen		= sock_no_listen,
187 	.shutdown	= sock_no_shutdown,
188 	.setsockopt	= sock_no_setsockopt,
189 	.getsockopt	= sock_no_getsockopt,
190 	.connect	= sock_no_connect,
191 	.socketpair	= sock_no_socketpair,
192 	.accept		= sock_no_accept,
193 	.mmap		= sock_no_mmap
194 };
195 
196 static struct proto cmtp_proto = {
197 	.name		= "CMTP",
198 	.owner		= THIS_MODULE,
199 	.obj_size	= sizeof(struct bt_sock)
200 };
201 
202 static int cmtp_sock_create(struct net *net, struct socket *sock, int protocol,
203 			    int kern)
204 {
205 	struct sock *sk;
206 
207 	BT_DBG("sock %p", sock);
208 
209 	if (sock->type != SOCK_RAW)
210 		return -ESOCKTNOSUPPORT;
211 
212 	sk = sk_alloc(net, PF_BLUETOOTH, GFP_ATOMIC, &cmtp_proto, kern);
213 	if (!sk)
214 		return -ENOMEM;
215 
216 	sock_init_data(sock, sk);
217 
218 	sock->ops = &cmtp_sock_ops;
219 
220 	sock->state = SS_UNCONNECTED;
221 
222 	sock_reset_flag(sk, SOCK_ZAPPED);
223 
224 	sk->sk_protocol = protocol;
225 	sk->sk_state    = BT_OPEN;
226 
227 	bt_sock_link(&cmtp_sk_list, sk);
228 
229 	return 0;
230 }
231 
232 static const struct net_proto_family cmtp_sock_family_ops = {
233 	.family	= PF_BLUETOOTH,
234 	.owner	= THIS_MODULE,
235 	.create	= cmtp_sock_create
236 };
237 
238 int cmtp_init_sockets(void)
239 {
240 	int err;
241 
242 	err = proto_register(&cmtp_proto, 0);
243 	if (err < 0)
244 		return err;
245 
246 	err = bt_sock_register(BTPROTO_CMTP, &cmtp_sock_family_ops);
247 	if (err < 0) {
248 		BT_ERR("Can't register CMTP socket");
249 		goto error;
250 	}
251 
252 	err = bt_procfs_init(&init_net, "cmtp", &cmtp_sk_list, NULL);
253 	if (err < 0) {
254 		BT_ERR("Failed to create CMTP proc file");
255 		bt_sock_unregister(BTPROTO_HIDP);
256 		goto error;
257 	}
258 
259 	BT_INFO("CMTP socket layer initialized");
260 
261 	return 0;
262 
263 error:
264 	proto_unregister(&cmtp_proto);
265 	return err;
266 }
267 
268 void cmtp_cleanup_sockets(void)
269 {
270 	bt_procfs_cleanup(&init_net, "cmtp");
271 	bt_sock_unregister(BTPROTO_CMTP);
272 	proto_unregister(&cmtp_proto);
273 }
274