Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/net/bluetooth/cmtp/sock.c
15112 views
1
/*
2
CMTP implementation for Linux Bluetooth stack (BlueZ).
3
Copyright (C) 2002-2003 Marcel Holtmann <[email protected]>
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/module.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
#include <asm/system.h>
43
44
#include "cmtp.h"
45
46
static int cmtp_sock_release(struct socket *sock)
47
{
48
struct sock *sk = sock->sk;
49
50
BT_DBG("sock %p sk %p", sock, sk);
51
52
if (!sk)
53
return 0;
54
55
sock_orphan(sk);
56
sock_put(sk);
57
58
return 0;
59
}
60
61
static int cmtp_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
62
{
63
struct cmtp_connadd_req ca;
64
struct cmtp_conndel_req cd;
65
struct cmtp_connlist_req cl;
66
struct cmtp_conninfo ci;
67
struct socket *nsock;
68
void __user *argp = (void __user *)arg;
69
int err;
70
71
BT_DBG("cmd %x arg %lx", cmd, arg);
72
73
switch (cmd) {
74
case CMTPCONNADD:
75
if (!capable(CAP_NET_ADMIN))
76
return -EACCES;
77
78
if (copy_from_user(&ca, argp, sizeof(ca)))
79
return -EFAULT;
80
81
nsock = sockfd_lookup(ca.sock, &err);
82
if (!nsock)
83
return err;
84
85
if (nsock->sk->sk_state != BT_CONNECTED) {
86
sockfd_put(nsock);
87
return -EBADFD;
88
}
89
90
err = cmtp_add_connection(&ca, nsock);
91
if (!err) {
92
if (copy_to_user(argp, &ca, sizeof(ca)))
93
err = -EFAULT;
94
} else
95
sockfd_put(nsock);
96
97
return err;
98
99
case CMTPCONNDEL:
100
if (!capable(CAP_NET_ADMIN))
101
return -EACCES;
102
103
if (copy_from_user(&cd, argp, sizeof(cd)))
104
return -EFAULT;
105
106
return cmtp_del_connection(&cd);
107
108
case CMTPGETCONNLIST:
109
if (copy_from_user(&cl, argp, sizeof(cl)))
110
return -EFAULT;
111
112
if (cl.cnum <= 0)
113
return -EINVAL;
114
115
err = cmtp_get_connlist(&cl);
116
if (!err && copy_to_user(argp, &cl, sizeof(cl)))
117
return -EFAULT;
118
119
return err;
120
121
case CMTPGETCONNINFO:
122
if (copy_from_user(&ci, argp, sizeof(ci)))
123
return -EFAULT;
124
125
err = cmtp_get_conninfo(&ci);
126
if (!err && copy_to_user(argp, &ci, sizeof(ci)))
127
return -EFAULT;
128
129
return err;
130
}
131
132
return -EINVAL;
133
}
134
135
#ifdef CONFIG_COMPAT
136
static int cmtp_sock_compat_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
137
{
138
if (cmd == CMTPGETCONNLIST) {
139
struct cmtp_connlist_req cl;
140
uint32_t uci;
141
int err;
142
143
if (get_user(cl.cnum, (uint32_t __user *) arg) ||
144
get_user(uci, (u32 __user *) (arg + 4)))
145
return -EFAULT;
146
147
cl.ci = compat_ptr(uci);
148
149
if (cl.cnum <= 0)
150
return -EINVAL;
151
152
err = cmtp_get_connlist(&cl);
153
154
if (!err && put_user(cl.cnum, (uint32_t __user *) arg))
155
err = -EFAULT;
156
157
return err;
158
}
159
160
return cmtp_sock_ioctl(sock, cmd, arg);
161
}
162
#endif
163
164
static const struct proto_ops cmtp_sock_ops = {
165
.family = PF_BLUETOOTH,
166
.owner = THIS_MODULE,
167
.release = cmtp_sock_release,
168
.ioctl = cmtp_sock_ioctl,
169
#ifdef CONFIG_COMPAT
170
.compat_ioctl = cmtp_sock_compat_ioctl,
171
#endif
172
.bind = sock_no_bind,
173
.getname = sock_no_getname,
174
.sendmsg = sock_no_sendmsg,
175
.recvmsg = sock_no_recvmsg,
176
.poll = sock_no_poll,
177
.listen = sock_no_listen,
178
.shutdown = sock_no_shutdown,
179
.setsockopt = sock_no_setsockopt,
180
.getsockopt = sock_no_getsockopt,
181
.connect = sock_no_connect,
182
.socketpair = sock_no_socketpair,
183
.accept = sock_no_accept,
184
.mmap = sock_no_mmap
185
};
186
187
static struct proto cmtp_proto = {
188
.name = "CMTP",
189
.owner = THIS_MODULE,
190
.obj_size = sizeof(struct bt_sock)
191
};
192
193
static int cmtp_sock_create(struct net *net, struct socket *sock, int protocol,
194
int kern)
195
{
196
struct sock *sk;
197
198
BT_DBG("sock %p", sock);
199
200
if (sock->type != SOCK_RAW)
201
return -ESOCKTNOSUPPORT;
202
203
sk = sk_alloc(net, PF_BLUETOOTH, GFP_ATOMIC, &cmtp_proto);
204
if (!sk)
205
return -ENOMEM;
206
207
sock_init_data(sock, sk);
208
209
sock->ops = &cmtp_sock_ops;
210
211
sock->state = SS_UNCONNECTED;
212
213
sock_reset_flag(sk, SOCK_ZAPPED);
214
215
sk->sk_protocol = protocol;
216
sk->sk_state = BT_OPEN;
217
218
return 0;
219
}
220
221
static const struct net_proto_family cmtp_sock_family_ops = {
222
.family = PF_BLUETOOTH,
223
.owner = THIS_MODULE,
224
.create = cmtp_sock_create
225
};
226
227
int cmtp_init_sockets(void)
228
{
229
int err;
230
231
err = proto_register(&cmtp_proto, 0);
232
if (err < 0)
233
return err;
234
235
err = bt_sock_register(BTPROTO_CMTP, &cmtp_sock_family_ops);
236
if (err < 0)
237
goto error;
238
239
return 0;
240
241
error:
242
BT_ERR("Can't register CMTP socket");
243
proto_unregister(&cmtp_proto);
244
return err;
245
}
246
247
void cmtp_cleanup_sockets(void)
248
{
249
if (bt_sock_unregister(BTPROTO_CMTP) < 0)
250
BT_ERR("Can't unregister CMTP socket");
251
252
proto_unregister(&cmtp_proto);
253
}
254
255