root/net/bluetooth/bnep/sock.c

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

DEFINITIONS

This source file includes following definitions.
  1. bnep_sock_release
  2. do_bnep_sock_ioctl
  3. bnep_sock_ioctl
  4. bnep_sock_compat_ioctl
  5. bnep_sock_create
  6. bnep_sock_init
  7. bnep_sock_cleanup

   1 /*
   2    BNEP implementation for Linux Bluetooth stack (BlueZ).
   3    Copyright (C) 2001-2002 Inventel Systemes
   4    Written 2001-2002 by
   5         David Libault  <david.libault@inventel.fr>
   6 
   7    Copyright (C) 2002 Maxim Krasnyansky <maxk@qualcomm.com>
   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 do_bnep_sock_ioctl(struct socket *sock, unsigned int cmd, void __user *argp)
  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         __u32 supp_feat = BIT(BNEP_SETUP_RESPONSE);
  60         int err;
  61 
  62         BT_DBG("cmd %x arg %p", cmd, argp);
  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         case BNEPGETSUPPFEAT:
 124                 if (copy_to_user(argp, &supp_feat, sizeof(supp_feat)))
 125                         return -EFAULT;
 126 
 127                 return 0;
 128 
 129         default:
 130                 return -EINVAL;
 131         }
 132 
 133         return 0;
 134 }
 135 
 136 static int bnep_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
 137 {
 138         return do_bnep_sock_ioctl(sock, cmd, (void __user *)arg);
 139 }
 140 
 141 #ifdef CONFIG_COMPAT
 142 static int bnep_sock_compat_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
 143 {
 144         void __user *argp = compat_ptr(arg);
 145         if (cmd == BNEPGETCONNLIST) {
 146                 struct bnep_connlist_req cl;
 147                 unsigned __user *p = argp;
 148                 u32 uci;
 149                 int err;
 150 
 151                 if (get_user(cl.cnum, p) || get_user(uci, p + 1))
 152                         return -EFAULT;
 153 
 154                 cl.ci = compat_ptr(uci);
 155 
 156                 if (cl.cnum <= 0)
 157                         return -EINVAL;
 158 
 159                 err = bnep_get_connlist(&cl);
 160 
 161                 if (!err && put_user(cl.cnum, p))
 162                         err = -EFAULT;
 163 
 164                 return err;
 165         }
 166 
 167         return do_bnep_sock_ioctl(sock, cmd, argp);
 168 }
 169 #endif
 170 
 171 static const struct proto_ops bnep_sock_ops = {
 172         .family         = PF_BLUETOOTH,
 173         .owner          = THIS_MODULE,
 174         .release        = bnep_sock_release,
 175         .ioctl          = bnep_sock_ioctl,
 176 #ifdef CONFIG_COMPAT
 177         .compat_ioctl   = bnep_sock_compat_ioctl,
 178 #endif
 179         .bind           = sock_no_bind,
 180         .getname        = sock_no_getname,
 181         .sendmsg        = sock_no_sendmsg,
 182         .recvmsg        = sock_no_recvmsg,
 183         .listen         = sock_no_listen,
 184         .shutdown       = sock_no_shutdown,
 185         .setsockopt     = sock_no_setsockopt,
 186         .getsockopt     = sock_no_getsockopt,
 187         .connect        = sock_no_connect,
 188         .socketpair     = sock_no_socketpair,
 189         .accept         = sock_no_accept,
 190         .mmap           = sock_no_mmap
 191 };
 192 
 193 static struct proto bnep_proto = {
 194         .name           = "BNEP",
 195         .owner          = THIS_MODULE,
 196         .obj_size       = sizeof(struct bt_sock)
 197 };
 198 
 199 static int bnep_sock_create(struct net *net, struct socket *sock, int protocol,
 200                             int kern)
 201 {
 202         struct sock *sk;
 203 
 204         BT_DBG("sock %p", sock);
 205 
 206         if (sock->type != SOCK_RAW)
 207                 return -ESOCKTNOSUPPORT;
 208 
 209         sk = sk_alloc(net, PF_BLUETOOTH, GFP_ATOMIC, &bnep_proto, kern);
 210         if (!sk)
 211                 return -ENOMEM;
 212 
 213         sock_init_data(sock, sk);
 214 
 215         sock->ops = &bnep_sock_ops;
 216 
 217         sock->state = SS_UNCONNECTED;
 218 
 219         sock_reset_flag(sk, SOCK_ZAPPED);
 220 
 221         sk->sk_protocol = protocol;
 222         sk->sk_state    = BT_OPEN;
 223 
 224         bt_sock_link(&bnep_sk_list, sk);
 225         return 0;
 226 }
 227 
 228 static const struct net_proto_family bnep_sock_family_ops = {
 229         .family = PF_BLUETOOTH,
 230         .owner  = THIS_MODULE,
 231         .create = bnep_sock_create
 232 };
 233 
 234 int __init bnep_sock_init(void)
 235 {
 236         int err;
 237 
 238         err = proto_register(&bnep_proto, 0);
 239         if (err < 0)
 240                 return err;
 241 
 242         err = bt_sock_register(BTPROTO_BNEP, &bnep_sock_family_ops);
 243         if (err < 0) {
 244                 BT_ERR("Can't register BNEP socket");
 245                 goto error;
 246         }
 247 
 248         err = bt_procfs_init(&init_net, "bnep", &bnep_sk_list, NULL);
 249         if (err < 0) {
 250                 BT_ERR("Failed to create BNEP proc file");
 251                 bt_sock_unregister(BTPROTO_BNEP);
 252                 goto error;
 253         }
 254 
 255         BT_INFO("BNEP socket layer initialized");
 256 
 257         return 0;
 258 
 259 error:
 260         proto_unregister(&bnep_proto);
 261         return err;
 262 }
 263 
 264 void __exit bnep_sock_cleanup(void)
 265 {
 266         bt_procfs_cleanup(&init_net, "bnep");
 267         bt_sock_unregister(BTPROTO_BNEP);
 268         proto_unregister(&bnep_proto);
 269 }

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