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