Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
sock.c
Go to the documentation of this file.
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/export.h>
28 #include <linux/file.h>
29 
30 #include "bnep.h"
31 
32 static struct bt_sock_list bnep_sk_list = {
33  .lock = __RW_LOCK_UNLOCKED(bnep_sk_list.lock)
34 };
35 
36 static 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 
52 static 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
131 static 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 
159 static 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 
182 static struct proto bnep_proto = {
183  .name = "BNEP",
184  .owner = THIS_MODULE,
185  .obj_size = sizeof(struct bt_sock)
186 };
187 
188 static 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 
217 static const struct net_proto_family bnep_sock_family_ops = {
218  .family = PF_BLUETOOTH,
219  .owner = THIS_MODULE,
220  .create = bnep_sock_create
221 };
222 
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(THIS_MODULE, &init_net, "bnep", &bnep_sk_list, NULL);
238  if (err < 0) {
239  BT_ERR("Failed to create BNEP proc file");
241  goto error;
242  }
243 
244  BT_INFO("BNEP socket layer initialized");
245 
246  return 0;
247 
248 error:
249  proto_unregister(&bnep_proto);
250  return err;
251 }
252 
254 {
255  bt_procfs_cleanup(&init_net, "bnep");
257  BT_ERR("Can't unregister BNEP socket");
258 
259  proto_unregister(&bnep_proto);
260 }