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