Back to home page

OSCL-LXR

 
 

    


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