Back to home page

OSCL-LXR

 
 

    


0001 /*
0002    BNEP implementation for Linux Bluetooth stack (BlueZ).
0003    Copyright (C) 2001-2002 Inventel Systemes
0004    Written 2001-2002 by
0005     David Libault  <david.libault@inventel.fr>
0006 
0007    Copyright (C) 2002 Maxim Krasnyansky <maxk@qualcomm.com>
0008 
0009    This program is free software; you can redistribute it and/or modify
0010    it under the terms of the GNU General Public License version 2 as
0011    published by the Free Software Foundation;
0012 
0013    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
0014    OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
0015    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
0016    IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
0017    CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
0018    WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
0019    ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
0020    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
0021 
0022    ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
0023    COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
0024    SOFTWARE IS DISCLAIMED.
0025 */
0026 
0027 #include <linux/compat.h>
0028 #include <linux/export.h>
0029 #include <linux/file.h>
0030 
0031 #include "bnep.h"
0032 
0033 static struct bt_sock_list bnep_sk_list = {
0034     .lock = __RW_LOCK_UNLOCKED(bnep_sk_list.lock)
0035 };
0036 
0037 static int bnep_sock_release(struct socket *sock)
0038 {
0039     struct sock *sk = sock->sk;
0040 
0041     BT_DBG("sock %p sk %p", sock, sk);
0042 
0043     if (!sk)
0044         return 0;
0045 
0046     bt_sock_unlink(&bnep_sk_list, sk);
0047 
0048     sock_orphan(sk);
0049     sock_put(sk);
0050     return 0;
0051 }
0052 
0053 static int do_bnep_sock_ioctl(struct socket *sock, unsigned int cmd, void __user *argp)
0054 {
0055     struct bnep_connlist_req cl;
0056     struct bnep_connadd_req  ca;
0057     struct bnep_conndel_req  cd;
0058     struct bnep_conninfo ci;
0059     struct socket *nsock;
0060     __u32 supp_feat = BIT(BNEP_SETUP_RESPONSE);
0061     int err;
0062 
0063     BT_DBG("cmd %x arg %p", cmd, argp);
0064 
0065     switch (cmd) {
0066     case BNEPCONNADD:
0067         if (!capable(CAP_NET_ADMIN))
0068             return -EPERM;
0069 
0070         if (copy_from_user(&ca, argp, sizeof(ca)))
0071             return -EFAULT;
0072 
0073         nsock = sockfd_lookup(ca.sock, &err);
0074         if (!nsock)
0075             return err;
0076 
0077         if (nsock->sk->sk_state != BT_CONNECTED) {
0078             sockfd_put(nsock);
0079             return -EBADFD;
0080         }
0081         ca.device[sizeof(ca.device)-1] = 0;
0082 
0083         err = bnep_add_connection(&ca, nsock);
0084         if (!err) {
0085             if (copy_to_user(argp, &ca, sizeof(ca)))
0086                 err = -EFAULT;
0087         } else
0088             sockfd_put(nsock);
0089 
0090         return err;
0091 
0092     case BNEPCONNDEL:
0093         if (!capable(CAP_NET_ADMIN))
0094             return -EPERM;
0095 
0096         if (copy_from_user(&cd, argp, sizeof(cd)))
0097             return -EFAULT;
0098 
0099         return bnep_del_connection(&cd);
0100 
0101     case BNEPGETCONNLIST:
0102         if (copy_from_user(&cl, argp, sizeof(cl)))
0103             return -EFAULT;
0104 
0105         if (cl.cnum <= 0)
0106             return -EINVAL;
0107 
0108         err = bnep_get_connlist(&cl);
0109         if (!err && copy_to_user(argp, &cl, sizeof(cl)))
0110             return -EFAULT;
0111 
0112         return err;
0113 
0114     case BNEPGETCONNINFO:
0115         if (copy_from_user(&ci, argp, sizeof(ci)))
0116             return -EFAULT;
0117 
0118         err = bnep_get_conninfo(&ci);
0119         if (!err && copy_to_user(argp, &ci, sizeof(ci)))
0120             return -EFAULT;
0121 
0122         return err;
0123 
0124     case BNEPGETSUPPFEAT:
0125         if (copy_to_user(argp, &supp_feat, sizeof(supp_feat)))
0126             return -EFAULT;
0127 
0128         return 0;
0129 
0130     default:
0131         return -EINVAL;
0132     }
0133 
0134     return 0;
0135 }
0136 
0137 static int bnep_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
0138 {
0139     return do_bnep_sock_ioctl(sock, cmd, (void __user *)arg);
0140 }
0141 
0142 #ifdef CONFIG_COMPAT
0143 static int bnep_sock_compat_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
0144 {
0145     void __user *argp = compat_ptr(arg);
0146     if (cmd == BNEPGETCONNLIST) {
0147         struct bnep_connlist_req cl;
0148         unsigned __user *p = argp;
0149         u32 uci;
0150         int err;
0151 
0152         if (get_user(cl.cnum, p) || get_user(uci, p + 1))
0153             return -EFAULT;
0154 
0155         cl.ci = compat_ptr(uci);
0156 
0157         if (cl.cnum <= 0)
0158             return -EINVAL;
0159 
0160         err = bnep_get_connlist(&cl);
0161 
0162         if (!err && put_user(cl.cnum, p))
0163             err = -EFAULT;
0164 
0165         return err;
0166     }
0167 
0168     return do_bnep_sock_ioctl(sock, cmd, argp);
0169 }
0170 #endif
0171 
0172 static const struct proto_ops bnep_sock_ops = {
0173     .family     = PF_BLUETOOTH,
0174     .owner      = THIS_MODULE,
0175     .release    = bnep_sock_release,
0176     .ioctl      = bnep_sock_ioctl,
0177 #ifdef CONFIG_COMPAT
0178     .compat_ioctl   = bnep_sock_compat_ioctl,
0179 #endif
0180     .bind       = sock_no_bind,
0181     .getname    = sock_no_getname,
0182     .sendmsg    = sock_no_sendmsg,
0183     .recvmsg    = sock_no_recvmsg,
0184     .listen     = sock_no_listen,
0185     .shutdown   = sock_no_shutdown,
0186     .connect    = sock_no_connect,
0187     .socketpair = sock_no_socketpair,
0188     .accept     = sock_no_accept,
0189     .mmap       = sock_no_mmap
0190 };
0191 
0192 static struct proto bnep_proto = {
0193     .name       = "BNEP",
0194     .owner      = THIS_MODULE,
0195     .obj_size   = sizeof(struct bt_sock)
0196 };
0197 
0198 static int bnep_sock_create(struct net *net, struct socket *sock, int protocol,
0199                 int kern)
0200 {
0201     struct sock *sk;
0202 
0203     BT_DBG("sock %p", sock);
0204 
0205     if (sock->type != SOCK_RAW)
0206         return -ESOCKTNOSUPPORT;
0207 
0208     sk = sk_alloc(net, PF_BLUETOOTH, GFP_ATOMIC, &bnep_proto, kern);
0209     if (!sk)
0210         return -ENOMEM;
0211 
0212     sock_init_data(sock, sk);
0213 
0214     sock->ops = &bnep_sock_ops;
0215 
0216     sock->state = SS_UNCONNECTED;
0217 
0218     sock_reset_flag(sk, SOCK_ZAPPED);
0219 
0220     sk->sk_protocol = protocol;
0221     sk->sk_state    = BT_OPEN;
0222 
0223     bt_sock_link(&bnep_sk_list, sk);
0224     return 0;
0225 }
0226 
0227 static const struct net_proto_family bnep_sock_family_ops = {
0228     .family = PF_BLUETOOTH,
0229     .owner  = THIS_MODULE,
0230     .create = bnep_sock_create
0231 };
0232 
0233 int __init bnep_sock_init(void)
0234 {
0235     int err;
0236 
0237     err = proto_register(&bnep_proto, 0);
0238     if (err < 0)
0239         return err;
0240 
0241     err = bt_sock_register(BTPROTO_BNEP, &bnep_sock_family_ops);
0242     if (err < 0) {
0243         BT_ERR("Can't register BNEP socket");
0244         goto error;
0245     }
0246 
0247     err = bt_procfs_init(&init_net, "bnep", &bnep_sk_list, NULL);
0248     if (err < 0) {
0249         BT_ERR("Failed to create BNEP proc file");
0250         bt_sock_unregister(BTPROTO_BNEP);
0251         goto error;
0252     }
0253 
0254     BT_INFO("BNEP socket layer initialized");
0255 
0256     return 0;
0257 
0258 error:
0259     proto_unregister(&bnep_proto);
0260     return err;
0261 }
0262 
0263 void __exit bnep_sock_cleanup(void)
0264 {
0265     bt_procfs_cleanup(&init_net, "bnep");
0266     bt_sock_unregister(BTPROTO_BNEP);
0267     proto_unregister(&bnep_proto);
0268 }