Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/net/bluetooth/bnep/sock.c
15112 views
1
/*
2
BNEP implementation for Linux Bluetooth stack (BlueZ).
3
Copyright (C) 2001-2002 Inventel Systemes
4
Written 2001-2002 by
5
David Libault <[email protected]>
6
7
Copyright (C) 2002 Maxim Krasnyansky <[email protected]>
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/module.h>
28
29
#include <linux/types.h>
30
#include <linux/capability.h>
31
#include <linux/errno.h>
32
#include <linux/kernel.h>
33
#include <linux/poll.h>
34
#include <linux/fcntl.h>
35
#include <linux/skbuff.h>
36
#include <linux/socket.h>
37
#include <linux/ioctl.h>
38
#include <linux/file.h>
39
#include <linux/init.h>
40
#include <linux/compat.h>
41
#include <linux/gfp.h>
42
#include <linux/uaccess.h>
43
#include <net/sock.h>
44
45
#include <asm/system.h>
46
47
#include "bnep.h"
48
49
static int bnep_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
sock_orphan(sk);
59
sock_put(sk);
60
return 0;
61
}
62
63
static int bnep_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
64
{
65
struct bnep_connlist_req cl;
66
struct bnep_connadd_req ca;
67
struct bnep_conndel_req cd;
68
struct bnep_conninfo ci;
69
struct socket *nsock;
70
void __user *argp = (void __user *)arg;
71
int err;
72
73
BT_DBG("cmd %x arg %lx", cmd, arg);
74
75
switch (cmd) {
76
case BNEPCONNADD:
77
if (!capable(CAP_NET_ADMIN))
78
return -EACCES;
79
80
if (copy_from_user(&ca, argp, sizeof(ca)))
81
return -EFAULT;
82
83
nsock = sockfd_lookup(ca.sock, &err);
84
if (!nsock)
85
return err;
86
87
if (nsock->sk->sk_state != BT_CONNECTED) {
88
sockfd_put(nsock);
89
return -EBADFD;
90
}
91
ca.device[sizeof(ca.device)-1] = 0;
92
93
err = bnep_add_connection(&ca, nsock);
94
if (!err) {
95
if (copy_to_user(argp, &ca, sizeof(ca)))
96
err = -EFAULT;
97
} else
98
sockfd_put(nsock);
99
100
return err;
101
102
case BNEPCONNDEL:
103
if (!capable(CAP_NET_ADMIN))
104
return -EACCES;
105
106
if (copy_from_user(&cd, argp, sizeof(cd)))
107
return -EFAULT;
108
109
return bnep_del_connection(&cd);
110
111
case BNEPGETCONNLIST:
112
if (copy_from_user(&cl, argp, sizeof(cl)))
113
return -EFAULT;
114
115
if (cl.cnum <= 0)
116
return -EINVAL;
117
118
err = bnep_get_connlist(&cl);
119
if (!err && copy_to_user(argp, &cl, sizeof(cl)))
120
return -EFAULT;
121
122
return err;
123
124
case BNEPGETCONNINFO:
125
if (copy_from_user(&ci, argp, sizeof(ci)))
126
return -EFAULT;
127
128
err = bnep_get_conninfo(&ci);
129
if (!err && copy_to_user(argp, &ci, sizeof(ci)))
130
return -EFAULT;
131
132
return err;
133
134
default:
135
return -EINVAL;
136
}
137
138
return 0;
139
}
140
141
#ifdef CONFIG_COMPAT
142
static int bnep_sock_compat_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
143
{
144
if (cmd == BNEPGETCONNLIST) {
145
struct bnep_connlist_req cl;
146
uint32_t uci;
147
int err;
148
149
if (get_user(cl.cnum, (uint32_t __user *) arg) ||
150
get_user(uci, (u32 __user *) (arg + 4)))
151
return -EFAULT;
152
153
cl.ci = compat_ptr(uci);
154
155
if (cl.cnum <= 0)
156
return -EINVAL;
157
158
err = bnep_get_connlist(&cl);
159
160
if (!err && put_user(cl.cnum, (uint32_t __user *) arg))
161
err = -EFAULT;
162
163
return err;
164
}
165
166
return bnep_sock_ioctl(sock, cmd, arg);
167
}
168
#endif
169
170
static const struct proto_ops bnep_sock_ops = {
171
.family = PF_BLUETOOTH,
172
.owner = THIS_MODULE,
173
.release = bnep_sock_release,
174
.ioctl = bnep_sock_ioctl,
175
#ifdef CONFIG_COMPAT
176
.compat_ioctl = bnep_sock_compat_ioctl,
177
#endif
178
.bind = sock_no_bind,
179
.getname = sock_no_getname,
180
.sendmsg = sock_no_sendmsg,
181
.recvmsg = sock_no_recvmsg,
182
.poll = sock_no_poll,
183
.listen = sock_no_listen,
184
.shutdown = sock_no_shutdown,
185
.setsockopt = sock_no_setsockopt,
186
.getsockopt = sock_no_getsockopt,
187
.connect = sock_no_connect,
188
.socketpair = sock_no_socketpair,
189
.accept = sock_no_accept,
190
.mmap = sock_no_mmap
191
};
192
193
static struct proto bnep_proto = {
194
.name = "BNEP",
195
.owner = THIS_MODULE,
196
.obj_size = sizeof(struct bt_sock)
197
};
198
199
static int bnep_sock_create(struct net *net, struct socket *sock, int protocol,
200
int kern)
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(net, PF_BLUETOOTH, GFP_ATOMIC, &bnep_proto);
210
if (!sk)
211
return -ENOMEM;
212
213
sock_init_data(sock, sk);
214
215
sock->ops = &bnep_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 const struct net_proto_family bnep_sock_family_ops = {
228
.family = PF_BLUETOOTH,
229
.owner = THIS_MODULE,
230
.create = bnep_sock_create
231
};
232
233
int __init bnep_sock_init(void)
234
{
235
int err;
236
237
err = proto_register(&bnep_proto, 0);
238
if (err < 0)
239
return err;
240
241
err = bt_sock_register(BTPROTO_BNEP, &bnep_sock_family_ops);
242
if (err < 0)
243
goto error;
244
245
return 0;
246
247
error:
248
BT_ERR("Can't register BNEP socket");
249
proto_unregister(&bnep_proto);
250
return err;
251
}
252
253
void __exit bnep_sock_cleanup(void)
254
{
255
if (bt_sock_unregister(BTPROTO_BNEP) < 0)
256
BT_ERR("Can't unregister BNEP socket");
257
258
proto_unregister(&bnep_proto);
259
}
260
261