1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
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/slab.h>
34#include <linux/poll.h>
35#include <linux/fcntl.h>
36#include <linux/skbuff.h>
37#include <linux/socket.h>
38#include <linux/ioctl.h>
39#include <linux/file.h>
40#include <linux/init.h>
41#include <linux/compat.h>
42#include <net/sock.h>
43
44#include <asm/system.h>
45#include <asm/uaccess.h>
46
47#include "bnep.h"
48
49static 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
63static 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
92 err = bnep_add_connection(&ca, nsock);
93 if (!err) {
94 if (copy_to_user(argp, &ca, sizeof(ca)))
95 err = -EFAULT;
96 } else
97 sockfd_put(nsock);
98
99 return err;
100
101 case BNEPCONNDEL:
102 if (!capable(CAP_NET_ADMIN))
103 return -EACCES;
104
105 if (copy_from_user(&cd, argp, sizeof(cd)))
106 return -EFAULT;
107
108 return bnep_del_connection(&cd);
109
110 case BNEPGETCONNLIST:
111 if (copy_from_user(&cl, argp, sizeof(cl)))
112 return -EFAULT;
113
114 if (cl.cnum <= 0)
115 return -EINVAL;
116
117 err = bnep_get_connlist(&cl);
118 if (!err && copy_to_user(argp, &cl, sizeof(cl)))
119 return -EFAULT;
120
121 return err;
122
123 case BNEPGETCONNINFO:
124 if (copy_from_user(&ci, argp, sizeof(ci)))
125 return -EFAULT;
126
127 err = bnep_get_conninfo(&ci);
128 if (!err && copy_to_user(argp, &ci, sizeof(ci)))
129 return -EFAULT;
130
131 return err;
132
133 default:
134 return -EINVAL;
135 }
136
137 return 0;
138}
139
140#ifdef CONFIG_COMPAT
141static int bnep_sock_compat_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
142{
143 if (cmd == BNEPGETCONNLIST) {
144 struct bnep_connlist_req cl;
145 uint32_t uci;
146 int err;
147
148 if (get_user(cl.cnum, (uint32_t __user *) arg) ||
149 get_user(uci, (u32 __user *) (arg + 4)))
150 return -EFAULT;
151
152 cl.ci = compat_ptr(uci);
153
154 if (cl.cnum <= 0)
155 return -EINVAL;
156
157 err = bnep_get_connlist(&cl);
158
159 if (!err && put_user(cl.cnum, (uint32_t __user *) arg))
160 err = -EFAULT;
161
162 return err;
163 }
164
165 return bnep_sock_ioctl(sock, cmd, arg);
166}
167#endif
168
169static const struct proto_ops bnep_sock_ops = {
170 .family = PF_BLUETOOTH,
171 .owner = THIS_MODULE,
172 .release = bnep_sock_release,
173 .ioctl = bnep_sock_ioctl,
174#ifdef CONFIG_COMPAT
175 .compat_ioctl = bnep_sock_compat_ioctl,
176#endif
177 .bind = sock_no_bind,
178 .getname = sock_no_getname,
179 .sendmsg = sock_no_sendmsg,
180 .recvmsg = sock_no_recvmsg,
181 .poll = sock_no_poll,
182 .listen = sock_no_listen,
183 .shutdown = sock_no_shutdown,
184 .setsockopt = sock_no_setsockopt,
185 .getsockopt = sock_no_getsockopt,
186 .connect = sock_no_connect,
187 .socketpair = sock_no_socketpair,
188 .accept = sock_no_accept,
189 .mmap = sock_no_mmap
190};
191
192static struct proto bnep_proto = {
193 .name = "BNEP",
194 .owner = THIS_MODULE,
195 .obj_size = sizeof(struct bt_sock)
196};
197
198static int bnep_sock_create(struct net *net, struct socket *sock, int protocol)
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);
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 return 0;
223}
224
225static struct net_proto_family bnep_sock_family_ops = {
226 .family = PF_BLUETOOTH,
227 .owner = THIS_MODULE,
228 .create = bnep_sock_create
229};
230
231int __init bnep_sock_init(void)
232{
233 int err;
234
235 err = proto_register(&bnep_proto, 0);
236 if (err < 0)
237 return err;
238
239 err = bt_sock_register(BTPROTO_BNEP, &bnep_sock_family_ops);
240 if (err < 0)
241 goto error;
242
243 return 0;
244
245error:
246 BT_ERR("Can't register BNEP socket");
247 proto_unregister(&bnep_proto);
248 return err;
249}
250
251void __exit bnep_sock_cleanup(void)
252{
253 if (bt_sock_unregister(BTPROTO_BNEP) < 0)
254 BT_ERR("Can't unregister BNEP socket");
255
256 proto_unregister(&bnep_proto);
257}
258