Bluetooth: Unobfuscate tasklet_schedule usage
[safe/jmp/linux-2.6] / net / bluetooth / hci_sock.c
index 711a085..688cfeb 100644 (file)
@@ -1,4 +1,4 @@
-/* 
+/*
    BlueZ - Bluetooth protocol stack for Linux
    Copyright (C) 2000-2001 Qualcomm Incorporated
 
    BlueZ - Bluetooth protocol stack for Linux
    Copyright (C) 2000-2001 Qualcomm Incorporated
 
    OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
    IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
    OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
    IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
-   CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES 
-   WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 
-   ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 
+   CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
+   WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+   ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
-   ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS, 
-   COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS 
+   ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
+   COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
    SOFTWARE IS DISCLAIMED.
 */
 
    SOFTWARE IS DISCLAIMED.
 */
 
@@ -30,7 +30,6 @@
 #include <linux/capability.h>
 #include <linux/errno.h>
 #include <linux/kernel.h>
 #include <linux/capability.h>
 #include <linux/errno.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/poll.h>
 #include <linux/fcntl.h>
 #include <linux/slab.h>
 #include <linux/poll.h>
 #include <linux/fcntl.h>
@@ -38,6 +37,7 @@
 #include <linux/skbuff.h>
 #include <linux/workqueue.h>
 #include <linux/interrupt.h>
 #include <linux/skbuff.h>
 #include <linux/workqueue.h>
 #include <linux/interrupt.h>
+#include <linux/compat.h>
 #include <linux/socket.h>
 #include <linux/ioctl.h>
 #include <net/sock.h>
 #include <linux/socket.h>
 #include <linux/ioctl.h>
 #include <net/sock.h>
 #include <net/bluetooth/bluetooth.h>
 #include <net/bluetooth/hci_core.h>
 
 #include <net/bluetooth/bluetooth.h>
 #include <net/bluetooth/hci_core.h>
 
-#ifndef CONFIG_BT_HCI_SOCK_DEBUG
-#undef  BT_DBG
-#define BT_DBG(D...)
-#endif
-
 /* ----- HCI socket interface ----- */
 
 static inline int hci_test_bit(int nr, void *addr)
 /* ----- HCI socket interface ----- */
 
 static inline int hci_test_bit(int nr, void *addr)
@@ -71,20 +66,20 @@ static struct hci_sec_filter hci_sec_filter = {
        {
                { 0x0 },
                /* OGF_LINK_CTL */
        {
                { 0x0 },
                /* OGF_LINK_CTL */
-               { 0xbe000006, 0x00000001, 0x000000, 0x00 },
+               { 0xbe000006, 0x00000001, 0x00000000, 0x00 },
                /* OGF_LINK_POLICY */
                /* OGF_LINK_POLICY */
-               { 0x00005200, 0x00000000, 0x000000, 0x00 },
+               { 0x00005200, 0x00000000, 0x00000000, 0x00 },
                /* OGF_HOST_CTL */
                /* OGF_HOST_CTL */
-               { 0xaab00200, 0x2b402aaa, 0x020154, 0x00 },
+               { 0xaab00200, 0x2b402aaa, 0x05220154, 0x00 },
                /* OGF_INFO_PARAM */
                /* OGF_INFO_PARAM */
-               { 0x000002be, 0x00000000, 0x000000, 0x00 },
+               { 0x000002be, 0x00000000, 0x00000000, 0x00 },
                /* OGF_STATUS_PARAM */
                /* OGF_STATUS_PARAM */
-               { 0x000000ea, 0x00000000, 0x000000, 0x00 }
+               { 0x000000ea, 0x00000000, 0x00000000, 0x00 }
        }
 };
 
 static struct bt_sock_list hci_sk_list = {
        }
 };
 
 static struct bt_sock_list hci_sk_list = {
-       .lock = RW_LOCK_UNLOCKED
+       .lock = __RW_LOCK_UNLOCKED(hci_sk_list.lock)
 };
 
 /* Send frame to RAW socket */
 };
 
 /* Send frame to RAW socket */
@@ -123,10 +118,10 @@ void hci_send_to_sock(struct hci_dev *hdev, struct sk_buff *skb)
                        if (flt->opcode &&
                            ((evt == HCI_EV_CMD_COMPLETE &&
                              flt->opcode !=
                        if (flt->opcode &&
                            ((evt == HCI_EV_CMD_COMPLETE &&
                              flt->opcode !=
-                             get_unaligned((__u16 *)(skb->data + 3))) ||
+                             get_unaligned((__le16 *)(skb->data + 3))) ||
                             (evt == HCI_EV_CMD_STATUS &&
                              flt->opcode !=
                             (evt == HCI_EV_CMD_STATUS &&
                              flt->opcode !=
-                             get_unaligned((__u16 *)(skb->data + 4)))))
+                             get_unaligned((__le16 *)(skb->data + 4)))))
                                continue;
                }
 
                                continue;
                }
 
@@ -170,7 +165,7 @@ static int hci_sock_release(struct socket *sock)
        return 0;
 }
 
        return 0;
 }
 
-/* Ioctls that require bound socket */ 
+/* Ioctls that require bound socket */
 static inline int hci_sock_bound_ioctl(struct sock *sk, unsigned int cmd, unsigned long arg)
 {
        struct hci_dev *hdev = hci_pi(sk)->hdev;
 static inline int hci_sock_bound_ioctl(struct sock *sk, unsigned int cmd, unsigned long arg)
 {
        struct hci_dev *hdev = hci_pi(sk)->hdev;
@@ -193,19 +188,11 @@ static inline int hci_sock_bound_ioctl(struct sock *sk, unsigned int cmd, unsign
 
                return 0;
 
 
                return 0;
 
-       case HCISETSECMGR:
-               if (!capable(CAP_NET_ADMIN))
-                       return -EACCES;
-
-               if (arg)
-                       set_bit(HCI_SECMGR, &hdev->flags);
-               else
-                       clear_bit(HCI_SECMGR, &hdev->flags);
-
-               return 0;
-
        case HCIGETCONNINFO:
        case HCIGETCONNINFO:
-               return hci_get_conn_info(hdev, (void __user *)arg);
+               return hci_get_conn_info(hdev, (void __user *) arg);
+
+       case HCIGETAUTHINFO:
+               return hci_get_auth_info(hdev, (void __user *) arg);
 
        default:
                if (hdev->ioctl)
 
        default:
                if (hdev->ioctl)
@@ -217,7 +204,7 @@ static inline int hci_sock_bound_ioctl(struct sock *sk, unsigned int cmd, unsign
 static int hci_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
 {
        struct sock *sk = sock->sk;
 static int hci_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
 {
        struct sock *sk = sock->sk;
-       void __user *argp = (void __user *)arg;
+       void __user *argp = (void __user *) arg;
        int err;
 
        BT_DBG("cmd %x arg %lx", cmd, arg);
        int err;
 
        BT_DBG("cmd %x arg %lx", cmd, arg);
@@ -343,13 +330,28 @@ static inline void hci_sock_cmsg(struct sock *sk, struct msghdr *msg, struct sk_
 
        if (mask & HCI_CMSG_TSTAMP) {
                struct timeval tv;
 
        if (mask & HCI_CMSG_TSTAMP) {
                struct timeval tv;
+               void *data;
+               int len;
 
                skb_get_timestamp(skb, &tv);
 
                skb_get_timestamp(skb, &tv);
-               put_cmsg(msg, SOL_HCI, HCI_CMSG_TSTAMP, sizeof(tv), &tv);
+
+               data = &tv;
+               len = sizeof(tv);
+#ifdef CONFIG_COMPAT
+               if (msg->msg_flags & MSG_CMSG_COMPAT) {
+                       struct compat_timeval ctv;
+                       ctv.tv_sec = tv.tv_sec;
+                       ctv.tv_usec = tv.tv_usec;
+                       data = &ctv;
+                       len = sizeof(ctv);
+               }
+#endif
+
+               put_cmsg(msg, SOL_HCI, HCI_CMSG_TSTAMP, len, data);
        }
 }
        }
 }
-static int hci_sock_recvmsg(struct kiocb *iocb, struct socket *sock, 
+
+static int hci_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
                                struct msghdr *msg, size_t len, int flags)
 {
        int noblock = flags & MSG_DONTWAIT;
                                struct msghdr *msg, size_t len, int flags)
 {
        int noblock = flags & MSG_DONTWAIT;
@@ -376,7 +378,7 @@ static int hci_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
                copied = len;
        }
 
                copied = len;
        }
 
-       skb->h.raw = skb->data;
+       skb_reset_transport_header(skb);
        err = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied);
 
        hci_sock_cmsg(sk, msg, skb);
        err = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied);
 
        hci_sock_cmsg(sk, msg, skb);
@@ -386,7 +388,7 @@ static int hci_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
        return err ? : copied;
 }
 
        return err ? : copied;
 }
 
-static int hci_sock_sendmsg(struct kiocb *iocb, struct socket *sock, 
+static int hci_sock_sendmsg(struct kiocb *iocb, struct socket *sock,
                            struct msghdr *msg, size_t len)
 {
        struct sock *sk = sock->sk;
                            struct msghdr *msg, size_t len)
 {
        struct sock *sk = sock->sk;
@@ -412,6 +414,11 @@ static int hci_sock_sendmsg(struct kiocb *iocb, struct socket *sock,
                goto done;
        }
 
                goto done;
        }
 
+       if (!test_bit(HCI_UP, &hdev->flags)) {
+               err = -ENETDOWN;
+               goto done;
+       }
+
        if (!(skb = bt_skb_send_alloc(sk, len, msg->msg_flags & MSG_DONTWAIT, &err)))
                goto done;
 
        if (!(skb = bt_skb_send_alloc(sk, len, msg->msg_flags & MSG_DONTWAIT, &err)))
                goto done;
 
@@ -425,7 +432,7 @@ static int hci_sock_sendmsg(struct kiocb *iocb, struct socket *sock,
        skb->dev = (void *) hdev;
 
        if (bt_cb(skb)->pkt_type == HCI_COMMAND_PKT) {
        skb->dev = (void *) hdev;
 
        if (bt_cb(skb)->pkt_type == HCI_COMMAND_PKT) {
-               u16 opcode = __le16_to_cpu(get_unaligned((__le16 *) skb->data));
+               u16 opcode = get_unaligned_le16(skb->data);
                u16 ogf = hci_opcode_ogf(opcode);
                u16 ocf = hci_opcode_ocf(opcode);
 
                u16 ogf = hci_opcode_ogf(opcode);
                u16 ocf = hci_opcode_ocf(opcode);
 
@@ -436,12 +443,12 @@ static int hci_sock_sendmsg(struct kiocb *iocb, struct socket *sock,
                        goto drop;
                }
 
                        goto drop;
                }
 
-               if (test_bit(HCI_RAW, &hdev->flags) || (ogf == OGF_VENDOR_CMD)) {
+               if (test_bit(HCI_RAW, &hdev->flags) || (ogf == 0x3f)) {
                        skb_queue_tail(&hdev->raw_q, skb);
                        skb_queue_tail(&hdev->raw_q, skb);
-                       hci_sched_tx(hdev);
+                       tasklet_schedule(&hdev->tx_task);
                } else {
                        skb_queue_tail(&hdev->cmd_q, skb);
                } else {
                        skb_queue_tail(&hdev->cmd_q, skb);
-                       hci_sched_cmd(hdev);
+                       tasklet_schedule(&hdev->cmd_task);
                }
        } else {
                if (!capable(CAP_NET_RAW)) {
                }
        } else {
                if (!capable(CAP_NET_RAW)) {
@@ -450,7 +457,7 @@ static int hci_sock_sendmsg(struct kiocb *iocb, struct socket *sock,
                }
 
                skb_queue_tail(&hdev->raw_q, skb);
                }
 
                skb_queue_tail(&hdev->raw_q, skb);
-               hci_sched_tx(hdev);
+               tasklet_schedule(&hdev->tx_task);
        }
 
        err = len;
        }
 
        err = len;
@@ -464,7 +471,7 @@ drop:
        goto done;
 }
 
        goto done;
 }
 
-static int hci_sock_setsockopt(struct socket *sock, int level, int optname, char __user *optval, int len)
+static int hci_sock_setsockopt(struct socket *sock, int level, int optname, char __user *optval, unsigned int len)
 {
        struct hci_ufilter uf = { .opcode = 0 };
        struct sock *sk = sock->sk;
 {
        struct hci_ufilter uf = { .opcode = 0 };
        struct sock *sk = sock->sk;
@@ -500,6 +507,15 @@ static int hci_sock_setsockopt(struct socket *sock, int level, int optname, char
                break;
 
        case HCI_FILTER:
                break;
 
        case HCI_FILTER:
+               {
+                       struct hci_filter *f = &hci_pi(sk)->filter;
+
+                       uf.type_mask = f->type_mask;
+                       uf.opcode    = f->opcode;
+                       uf.event_mask[0] = *((u32 *) f->event_mask + 0);
+                       uf.event_mask[1] = *((u32 *) f->event_mask + 1);
+               }
+
                len = min_t(unsigned int, len, sizeof(uf));
                if (copy_from_user(&uf, optval, len)) {
                        err = -EFAULT;
                len = min_t(unsigned int, len, sizeof(uf));
                if (copy_from_user(&uf, optval, len)) {
                        err = -EFAULT;
@@ -520,7 +536,7 @@ static int hci_sock_setsockopt(struct socket *sock, int level, int optname, char
                        *((u32 *) f->event_mask + 0) = uf.event_mask[0];
                        *((u32 *) f->event_mask + 1) = uf.event_mask[1];
                }
                        *((u32 *) f->event_mask + 0) = uf.event_mask[0];
                        *((u32 *) f->event_mask + 1) = uf.event_mask[1];
                }
-               break; 
+               break;
 
        default:
                err = -ENOPROTOOPT;
 
        default:
                err = -ENOPROTOOPT;
@@ -535,7 +551,7 @@ static int hci_sock_getsockopt(struct socket *sock, int level, int optname, char
 {
        struct hci_ufilter uf;
        struct sock *sk = sock->sk;
 {
        struct hci_ufilter uf;
        struct sock *sk = sock->sk;
-       int len, opt; 
+       int len, opt;
 
        if (get_user(len, optlen))
                return -EFAULT;
 
        if (get_user(len, optlen))
                return -EFAULT;
@@ -544,7 +560,7 @@ static int hci_sock_getsockopt(struct socket *sock, int level, int optname, char
        case HCI_DATA_DIR:
                if (hci_pi(sk)->cmsg_mask & HCI_CMSG_DIR)
                        opt = 1;
        case HCI_DATA_DIR:
                if (hci_pi(sk)->cmsg_mask & HCI_CMSG_DIR)
                        opt = 1;
-               else 
+               else
                        opt = 0;
 
                if (put_user(opt, optval))
                        opt = 0;
 
                if (put_user(opt, optval))
@@ -554,7 +570,7 @@ static int hci_sock_getsockopt(struct socket *sock, int level, int optname, char
        case HCI_TIME_STAMP:
                if (hci_pi(sk)->cmsg_mask & HCI_CMSG_TSTAMP)
                        opt = 1;
        case HCI_TIME_STAMP:
                if (hci_pi(sk)->cmsg_mask & HCI_CMSG_TSTAMP)
                        opt = 1;
-               else 
+               else
                        opt = 0;
 
                if (put_user(opt, optval))
                        opt = 0;
 
                if (put_user(opt, optval))
@@ -610,7 +626,8 @@ static struct proto hci_sk_proto = {
        .obj_size       = sizeof(struct hci_pinfo)
 };
 
        .obj_size       = sizeof(struct hci_pinfo)
 };
 
-static int hci_sock_create(struct socket *sock, int protocol)
+static int hci_sock_create(struct net *net, struct socket *sock, int protocol,
+                          int kern)
 {
        struct sock *sk;
 
 {
        struct sock *sk;
 
@@ -621,7 +638,7 @@ static int hci_sock_create(struct socket *sock, int protocol)
 
        sock->ops = &hci_sock_ops;
 
 
        sock->ops = &hci_sock_ops;
 
-       sk = sk_alloc(PF_BLUETOOTH, GFP_ATOMIC, &hci_sk_proto, 1);
+       sk = sk_alloc(net, PF_BLUETOOTH, GFP_ATOMIC, &hci_sk_proto);
        if (!sk)
                return -ENOMEM;
 
        if (!sk)
                return -ENOMEM;
 
@@ -657,7 +674,8 @@ static int hci_sock_dev_event(struct notifier_block *this, unsigned long event,
                /* Detach sockets from device */
                read_lock(&hci_sk_list.lock);
                sk_for_each(sk, node, &hci_sk_list.head) {
                /* Detach sockets from device */
                read_lock(&hci_sk_list.lock);
                sk_for_each(sk, node, &hci_sk_list.head) {
-                       bh_lock_sock(sk);
+                       local_bh_disable();
+                       bh_lock_sock_nested(sk);
                        if (hci_pi(sk)->hdev == hdev) {
                                hci_pi(sk)->hdev = NULL;
                                sk->sk_err = EPIPE;
                        if (hci_pi(sk)->hdev == hdev) {
                                hci_pi(sk)->hdev = NULL;
                                sk->sk_err = EPIPE;
@@ -667,6 +685,7 @@ static int hci_sock_dev_event(struct notifier_block *this, unsigned long event,
                                hci_dev_put(hdev);
                        }
                        bh_unlock_sock(sk);
                                hci_dev_put(hdev);
                        }
                        bh_unlock_sock(sk);
+                       local_bh_enable();
                }
                read_unlock(&hci_sk_list.lock);
        }
                }
                read_unlock(&hci_sk_list.lock);
        }
@@ -674,7 +693,7 @@ static int hci_sock_dev_event(struct notifier_block *this, unsigned long event,
        return NOTIFY_DONE;
 }
 
        return NOTIFY_DONE;
 }
 
-static struct net_proto_family hci_sock_family_ops = {
+static const struct net_proto_family hci_sock_family_ops = {
        .family = PF_BLUETOOTH,
        .owner  = THIS_MODULE,
        .create = hci_sock_create,
        .family = PF_BLUETOOTH,
        .owner  = THIS_MODULE,
        .create = hci_sock_create,
@@ -708,7 +727,7 @@ error:
        return err;
 }
 
        return err;
 }
 
-int __exit hci_sock_cleanup(void)
+void __exit hci_sock_cleanup(void)
 {
        if (bt_sock_unregister(BTPROTO_HCI) < 0)
                BT_ERR("HCI socket unregistration failed");
 {
        if (bt_sock_unregister(BTPROTO_HCI) < 0)
                BT_ERR("HCI socket unregistration failed");
@@ -716,6 +735,4 @@ int __exit hci_sock_cleanup(void)
        hci_unregister_notifier(&hci_sock_nblock);
 
        proto_unregister(&hci_sk_proto);
        hci_unregister_notifier(&hci_sock_nblock);
 
        proto_unregister(&hci_sk_proto);
-
-       return 0;
 }
 }