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 .listen = sock_no_listen,
179 .shutdown = sock_no_shutdown,
180 .setsockopt = sock_no_setsockopt,
181 .getsockopt = sock_no_getsockopt,
182 .connect = sock_no_connect,
183 .socketpair = sock_no_socketpair,
184 .accept = sock_no_accept,
185 .mmap = sock_no_mmap
186};
187
188static struct proto bnep_proto = {
189 .name = "BNEP",
190 .owner = THIS_MODULE,
191 .obj_size = sizeof(struct bt_sock)
192};
193
194static int bnep_sock_create(struct net *net, struct socket *sock, int protocol,
195 int kern)
196{
197 struct sock *sk;
198
199 BT_DBG("sock %p", sock);
200
201 if (sock->type != SOCK_RAW)
202 return -ESOCKTNOSUPPORT;
203
204 sk = sk_alloc(net, PF_BLUETOOTH, GFP_ATOMIC, &bnep_proto, kern);
205 if (!sk)
206 return -ENOMEM;
207
208 sock_init_data(sock, sk);
209
210 sock->ops = &bnep_sock_ops;
211
212 sock->state = SS_UNCONNECTED;
213
214 sock_reset_flag(sk, SOCK_ZAPPED);
215
216 sk->sk_protocol = protocol;
217 sk->sk_state = BT_OPEN;
218
219 bt_sock_link(&bnep_sk_list, sk);
220 return 0;
221}
222
223static const struct net_proto_family bnep_sock_family_ops = {
224 .family = PF_BLUETOOTH,
225 .owner = THIS_MODULE,
226 .create = bnep_sock_create
227};
228
229int __init bnep_sock_init(void)
230{
231 int err;
232
233 err = proto_register(&bnep_proto, 0);
234 if (err < 0)
235 return err;
236
237 err = bt_sock_register(BTPROTO_BNEP, &bnep_sock_family_ops);
238 if (err < 0) {
239 BT_ERR("Can't register BNEP socket");
240 goto error;
241 }
242
243 err = bt_procfs_init(&init_net, "bnep", &bnep_sk_list, NULL);
244 if (err < 0) {
245 BT_ERR("Failed to create BNEP proc file");
246 bt_sock_unregister(BTPROTO_BNEP);
247 goto error;
248 }
249
250 BT_INFO("BNEP socket layer initialized");
251
252 return 0;
253
254error:
255 proto_unregister(&bnep_proto);
256 return err;
257}
258
259void __exit bnep_sock_cleanup(void)
260{
261 bt_procfs_cleanup(&init_net, "bnep");
262 bt_sock_unregister(BTPROTO_BNEP);
263 proto_unregister(&bnep_proto);
264}
265