root/net/bluetooth/hidp/sock.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. hidp_sock_release
  2. do_hidp_sock_ioctl
  3. hidp_sock_ioctl
  4. hidp_sock_compat_ioctl
  5. hidp_sock_create
  6. hidp_init_sockets
  7. hidp_cleanup_sockets

   1 /*
   2    HIDP implementation for Linux Bluetooth stack (BlueZ).
   3    Copyright (C) 2003-2004 Marcel Holtmann <marcel@holtmann.org>
   4 
   5    This program is free software; you can redistribute it and/or modify
   6    it under the terms of the GNU General Public License version 2 as
   7    published by the Free Software Foundation;
   8 
   9    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  10    OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  11    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
  12    IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
  13    CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
  14    WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  15    ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  16    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  17 
  18    ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
  19    COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
  20    SOFTWARE IS DISCLAIMED.
  21 */
  22 
  23 #include <linux/export.h>
  24 #include <linux/file.h>
  25 
  26 #include "hidp.h"
  27 
  28 static struct bt_sock_list hidp_sk_list = {
  29         .lock = __RW_LOCK_UNLOCKED(hidp_sk_list.lock)
  30 };
  31 
  32 static int hidp_sock_release(struct socket *sock)
  33 {
  34         struct sock *sk = sock->sk;
  35 
  36         BT_DBG("sock %p sk %p", sock, sk);
  37 
  38         if (!sk)
  39                 return 0;
  40 
  41         bt_sock_unlink(&hidp_sk_list, sk);
  42 
  43         sock_orphan(sk);
  44         sock_put(sk);
  45 
  46         return 0;
  47 }
  48 
  49 static int do_hidp_sock_ioctl(struct socket *sock, unsigned int cmd, void __user *argp)
  50 {
  51         struct hidp_connadd_req ca;
  52         struct hidp_conndel_req cd;
  53         struct hidp_connlist_req cl;
  54         struct hidp_conninfo ci;
  55         struct socket *csock;
  56         struct socket *isock;
  57         int err;
  58 
  59         BT_DBG("cmd %x arg %p", cmd, argp);
  60 
  61         switch (cmd) {
  62         case HIDPCONNADD:
  63                 if (!capable(CAP_NET_ADMIN))
  64                         return -EPERM;
  65 
  66                 if (copy_from_user(&ca, argp, sizeof(ca)))
  67                         return -EFAULT;
  68 
  69                 csock = sockfd_lookup(ca.ctrl_sock, &err);
  70                 if (!csock)
  71                         return err;
  72 
  73                 isock = sockfd_lookup(ca.intr_sock, &err);
  74                 if (!isock) {
  75                         sockfd_put(csock);
  76                         return err;
  77                 }
  78                 ca.name[sizeof(ca.name)-1] = 0;
  79 
  80                 err = hidp_connection_add(&ca, csock, isock);
  81                 if (!err && copy_to_user(argp, &ca, sizeof(ca)))
  82                         err = -EFAULT;
  83 
  84                 sockfd_put(csock);
  85                 sockfd_put(isock);
  86 
  87                 return err;
  88 
  89         case HIDPCONNDEL:
  90                 if (!capable(CAP_NET_ADMIN))
  91                         return -EPERM;
  92 
  93                 if (copy_from_user(&cd, argp, sizeof(cd)))
  94                         return -EFAULT;
  95 
  96                 return hidp_connection_del(&cd);
  97 
  98         case HIDPGETCONNLIST:
  99                 if (copy_from_user(&cl, argp, sizeof(cl)))
 100                         return -EFAULT;
 101 
 102                 if (cl.cnum <= 0)
 103                         return -EINVAL;
 104 
 105                 err = hidp_get_connlist(&cl);
 106                 if (!err && copy_to_user(argp, &cl, sizeof(cl)))
 107                         return -EFAULT;
 108 
 109                 return err;
 110 
 111         case HIDPGETCONNINFO:
 112                 if (copy_from_user(&ci, argp, sizeof(ci)))
 113                         return -EFAULT;
 114 
 115                 err = hidp_get_conninfo(&ci);
 116                 if (!err && copy_to_user(argp, &ci, sizeof(ci)))
 117                         return -EFAULT;
 118 
 119                 return err;
 120         }
 121 
 122         return -EINVAL;
 123 }
 124 
 125 static int hidp_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
 126 {
 127         return do_hidp_sock_ioctl(sock, cmd, (void __user *)arg);
 128 }
 129 
 130 #ifdef CONFIG_COMPAT
 131 struct compat_hidp_connadd_req {
 132         int   ctrl_sock;        /* Connected control socket */
 133         int   intr_sock;        /* Connected interrupt socket */
 134         __u16 parser;
 135         __u16 rd_size;
 136         compat_uptr_t rd_data;
 137         __u8  country;
 138         __u8  subclass;
 139         __u16 vendor;
 140         __u16 product;
 141         __u16 version;
 142         __u32 flags;
 143         __u32 idle_to;
 144         char  name[128];
 145 };
 146 
 147 static int hidp_sock_compat_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
 148 {
 149         void __user *argp = compat_ptr(arg);
 150         int err;
 151 
 152         if (cmd == HIDPGETCONNLIST) {
 153                 struct hidp_connlist_req cl;
 154                 u32 __user *p = argp;
 155                 u32 uci;
 156 
 157                 if (get_user(cl.cnum, p) || get_user(uci, p + 1))
 158                         return -EFAULT;
 159 
 160                 cl.ci = compat_ptr(uci);
 161 
 162                 if (cl.cnum <= 0)
 163                         return -EINVAL;
 164 
 165                 err = hidp_get_connlist(&cl);
 166 
 167                 if (!err && put_user(cl.cnum, p))
 168                         err = -EFAULT;
 169 
 170                 return err;
 171         } else if (cmd == HIDPCONNADD) {
 172                 struct compat_hidp_connadd_req ca32;
 173                 struct hidp_connadd_req ca;
 174                 struct socket *csock;
 175                 struct socket *isock;
 176 
 177                 if (!capable(CAP_NET_ADMIN))
 178                         return -EPERM;
 179 
 180                 if (copy_from_user(&ca32, (void __user *) arg, sizeof(ca32)))
 181                         return -EFAULT;
 182 
 183                 ca.ctrl_sock = ca32.ctrl_sock;
 184                 ca.intr_sock = ca32.intr_sock;
 185                 ca.parser = ca32.parser;
 186                 ca.rd_size = ca32.rd_size;
 187                 ca.rd_data = compat_ptr(ca32.rd_data);
 188                 ca.country = ca32.country;
 189                 ca.subclass = ca32.subclass;
 190                 ca.vendor = ca32.vendor;
 191                 ca.product = ca32.product;
 192                 ca.version = ca32.version;
 193                 ca.flags = ca32.flags;
 194                 ca.idle_to = ca32.idle_to;
 195                 ca32.name[sizeof(ca32.name) - 1] = '\0';
 196                 memcpy(ca.name, ca32.name, 128);
 197 
 198                 csock = sockfd_lookup(ca.ctrl_sock, &err);
 199                 if (!csock)
 200                         return err;
 201 
 202                 isock = sockfd_lookup(ca.intr_sock, &err);
 203                 if (!isock) {
 204                         sockfd_put(csock);
 205                         return err;
 206                 }
 207 
 208                 err = hidp_connection_add(&ca, csock, isock);
 209                 if (!err && copy_to_user(argp, &ca32, sizeof(ca32)))
 210                         err = -EFAULT;
 211 
 212                 sockfd_put(csock);
 213                 sockfd_put(isock);
 214 
 215                 return err;
 216         }
 217 
 218         return hidp_sock_ioctl(sock, cmd, arg);
 219 }
 220 #endif
 221 
 222 static const struct proto_ops hidp_sock_ops = {
 223         .family         = PF_BLUETOOTH,
 224         .owner          = THIS_MODULE,
 225         .release        = hidp_sock_release,
 226         .ioctl          = hidp_sock_ioctl,
 227 #ifdef CONFIG_COMPAT
 228         .compat_ioctl   = hidp_sock_compat_ioctl,
 229 #endif
 230         .bind           = sock_no_bind,
 231         .getname        = sock_no_getname,
 232         .sendmsg        = sock_no_sendmsg,
 233         .recvmsg        = sock_no_recvmsg,
 234         .listen         = sock_no_listen,
 235         .shutdown       = sock_no_shutdown,
 236         .setsockopt     = sock_no_setsockopt,
 237         .getsockopt     = sock_no_getsockopt,
 238         .connect        = sock_no_connect,
 239         .socketpair     = sock_no_socketpair,
 240         .accept         = sock_no_accept,
 241         .mmap           = sock_no_mmap
 242 };
 243 
 244 static struct proto hidp_proto = {
 245         .name           = "HIDP",
 246         .owner          = THIS_MODULE,
 247         .obj_size       = sizeof(struct bt_sock)
 248 };
 249 
 250 static int hidp_sock_create(struct net *net, struct socket *sock, int protocol,
 251                             int kern)
 252 {
 253         struct sock *sk;
 254 
 255         BT_DBG("sock %p", sock);
 256 
 257         if (sock->type != SOCK_RAW)
 258                 return -ESOCKTNOSUPPORT;
 259 
 260         sk = sk_alloc(net, PF_BLUETOOTH, GFP_ATOMIC, &hidp_proto, kern);
 261         if (!sk)
 262                 return -ENOMEM;
 263 
 264         sock_init_data(sock, sk);
 265 
 266         sock->ops = &hidp_sock_ops;
 267 
 268         sock->state = SS_UNCONNECTED;
 269 
 270         sock_reset_flag(sk, SOCK_ZAPPED);
 271 
 272         sk->sk_protocol = protocol;
 273         sk->sk_state    = BT_OPEN;
 274 
 275         bt_sock_link(&hidp_sk_list, sk);
 276 
 277         return 0;
 278 }
 279 
 280 static const struct net_proto_family hidp_sock_family_ops = {
 281         .family = PF_BLUETOOTH,
 282         .owner  = THIS_MODULE,
 283         .create = hidp_sock_create
 284 };
 285 
 286 int __init hidp_init_sockets(void)
 287 {
 288         int err;
 289 
 290         err = proto_register(&hidp_proto, 0);
 291         if (err < 0)
 292                 return err;
 293 
 294         err = bt_sock_register(BTPROTO_HIDP, &hidp_sock_family_ops);
 295         if (err < 0) {
 296                 BT_ERR("Can't register HIDP socket");
 297                 goto error;
 298         }
 299 
 300         err = bt_procfs_init(&init_net, "hidp", &hidp_sk_list, NULL);
 301         if (err < 0) {
 302                 BT_ERR("Failed to create HIDP proc file");
 303                 bt_sock_unregister(BTPROTO_HIDP);
 304                 goto error;
 305         }
 306 
 307         BT_INFO("HIDP socket layer initialized");
 308 
 309         return 0;
 310 
 311 error:
 312         proto_unregister(&hidp_proto);
 313         return err;
 314 }
 315 
 316 void __exit hidp_cleanup_sockets(void)
 317 {
 318         bt_procfs_cleanup(&init_net, "hidp");
 319         bt_sock_unregister(BTPROTO_HIDP);
 320         proto_unregister(&hidp_proto);
 321 }

/* [<][>][^][v][top][bottom][index][help] */