[PATCH] Simplify the registration of clocksources
[powerpc.git] / net / bluetooth / l2cap.c
index d56f60b..e83ee82 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.
 */
 
@@ -227,7 +227,7 @@ static void __l2cap_chan_add(struct l2cap_conn *conn, struct sock *sk, struct so
                bt_accept_enqueue(parent, sk);
 }
 
                bt_accept_enqueue(parent, sk);
 }
 
-/* Delete channel. 
+/* Delete channel.
  * Must be called on the locked socket. */
 static void l2cap_chan_del(struct sock *sk, int err)
 {
  * Must be called on the locked socket. */
 static void l2cap_chan_del(struct sock *sk, int err)
 {
@@ -238,7 +238,7 @@ static void l2cap_chan_del(struct sock *sk, int err)
 
        BT_DBG("sk %p, conn %p, err %d", sk, conn, err);
 
 
        BT_DBG("sk %p, conn %p, err %d", sk, conn, err);
 
-       if (conn) { 
+       if (conn) {
                /* Unlink from channel list */
                l2cap_chan_unlink(&conn->chan_list, sk);
                l2cap_pi(sk)->conn = NULL;
                /* Unlink from channel list */
                l2cap_chan_unlink(&conn->chan_list, sk);
                l2cap_pi(sk)->conn = NULL;
@@ -559,7 +559,7 @@ static int l2cap_sock_create(struct socket *sock, int protocol)
 
        sock->ops = &l2cap_sock_ops;
 
 
        sock->ops = &l2cap_sock_ops;
 
-       sk = l2cap_sock_alloc(sock, protocol, GFP_KERNEL);
+       sk = l2cap_sock_alloc(sock, protocol, GFP_ATOMIC);
        if (!sk)
                return -ENOMEM;
 
        if (!sk)
                return -ENOMEM;
 
@@ -585,6 +585,12 @@ static int l2cap_sock_bind(struct socket *sock, struct sockaddr *addr, int addr_
                goto done;
        }
 
                goto done;
        }
 
+       if (la->l2_psm > 0 && btohs(la->l2_psm) < 0x1001 &&
+                               !capable(CAP_NET_BIND_SERVICE)) {
+               err = -EACCES;
+               goto done;
+       }
+
        write_lock_bh(&l2cap_sk_list.lock);
 
        if (la->l2_psm && __l2cap_get_sock_by_addr(la->l2_psm, &la->l2_bdaddr)) {
        write_lock_bh(&l2cap_sk_list.lock);
 
        if (la->l2_psm && __l2cap_get_sock_by_addr(la->l2_psm, &la->l2_bdaddr)) {
@@ -770,7 +776,7 @@ static int l2cap_sock_accept(struct socket *sock, struct socket *newsock, int fl
        long timeo;
        int err = 0;
 
        long timeo;
        int err = 0;
 
-       lock_sock(sk);
+       lock_sock_nested(sk, SINGLE_DEPTH_NESTING);
 
        if (sk->sk_state != BT_LISTEN) {
                err = -EBADFD;
 
        if (sk->sk_state != BT_LISTEN) {
                err = -EBADFD;
@@ -792,7 +798,7 @@ static int l2cap_sock_accept(struct socket *sock, struct socket *newsock, int fl
 
                release_sock(sk);
                timeo = schedule_timeout(timeo);
 
                release_sock(sk);
                timeo = schedule_timeout(timeo);
-               lock_sock(sk);
+               lock_sock_nested(sk, SINGLE_DEPTH_NESTING);
 
                if (sk->sk_state != BT_LISTEN) {
                        err = -EBADFD;
 
                if (sk->sk_state != BT_LISTEN) {
                        err = -EBADFD;
@@ -884,7 +890,7 @@ static inline int l2cap_do_send(struct sock *sk, struct msghdr *msg, int len)
                *frag = bt_skb_send_alloc(sk, count, msg->msg_flags & MSG_DONTWAIT, &err);
                if (!*frag)
                        goto fail;
                *frag = bt_skb_send_alloc(sk, count, msg->msg_flags & MSG_DONTWAIT, &err);
                if (!*frag)
                        goto fail;
-               
+
                if (memcpy_fromiovec(skb_put(*frag, count), msg->msg_iov, count)) {
                        err = -EFAULT;
                        goto fail;
                if (memcpy_fromiovec(skb_put(*frag, count), msg->msg_iov, count)) {
                        err = -EFAULT;
                        goto fail;
@@ -1261,7 +1267,7 @@ static inline int l2cap_get_conf_opt(void **ptr, int *type, int *olen, unsigned
 
 static inline void l2cap_parse_conf_req(struct sock *sk, void *data, int len)
 {
 
 static inline void l2cap_parse_conf_req(struct sock *sk, void *data, int len)
 {
-       int type, hint, olen; 
+       int type, hint, olen;
        unsigned long val;
        void *ptr = data;
 
        unsigned long val;
        void *ptr = data;
 
@@ -1353,12 +1359,12 @@ static inline int l2cap_conf_output(struct sock *sk, void **ptr)
 
        /* Configure output options and let the other side know
         * which ones we don't like. */
 
        /* Configure output options and let the other side know
         * which ones we don't like. */
-       if (pi->conf_mtu < pi->omtu) {
-               l2cap_add_conf_opt(ptr, L2CAP_CONF_MTU, 2, pi->omtu);
+       if (pi->conf_mtu < pi->omtu)
                result = L2CAP_CONF_UNACCEPT;
                result = L2CAP_CONF_UNACCEPT;
-       } else {
+       else
                pi->omtu = pi->conf_mtu;
                pi->omtu = pi->conf_mtu;
-       }
+
+       l2cap_add_conf_opt(ptr, L2CAP_CONF_MTU, 2, pi->omtu);
 
        BT_DBG("sk %p result %d", sk, result);
        return result;
 
        BT_DBG("sk %p result %d", sk, result);
        return result;
@@ -1408,7 +1414,7 @@ static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hd
 
        /* Check for backlog size */
        if (sk_acceptq_is_full(parent)) {
 
        /* Check for backlog size */
        if (sk_acceptq_is_full(parent)) {
-               BT_DBG("backlog full %d", parent->sk_ack_backlog); 
+               BT_DBG("backlog full %d", parent->sk_ack_backlog);
                goto response;
        }
 
                goto response;
        }
 
@@ -1533,6 +1539,9 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr
        if (!(sk = l2cap_get_chan_by_scid(&conn->chan_list, dcid)))
                return -ENOENT;
 
        if (!(sk = l2cap_get_chan_by_scid(&conn->chan_list, dcid)))
                return -ENOENT;
 
+       if (sk->sk_state == BT_DISCONN)
+               goto unlock;
+
        l2cap_parse_conf_req(sk, req->data, cmd->len - sizeof(*req));
 
        if (flags & 0x0001) {
        l2cap_parse_conf_req(sk, req->data, cmd->len - sizeof(*req));
 
        if (flags & 0x0001) {
@@ -1598,7 +1607,7 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr
                        goto done;
                }
 
                        goto done;
                }
 
-       default: 
+       default:
                sk->sk_state = BT_DISCONN;
                sk->sk_err   = ECONNRESET;
                l2cap_sock_set_timer(sk, HZ * 5);
                sk->sk_state = BT_DISCONN;
                sk->sk_err   = ECONNRESET;
                l2cap_sock_set_timer(sk, HZ * 5);
@@ -2147,8 +2156,8 @@ static ssize_t l2cap_sysfs_show(struct class *dev, char *buf)
 
                str += sprintf(str, "%s %s %d %d 0x%4.4x 0x%4.4x %d %d 0x%x\n",
                                batostr(&bt_sk(sk)->src), batostr(&bt_sk(sk)->dst),
 
                str += sprintf(str, "%s %s %d %d 0x%4.4x 0x%4.4x %d %d 0x%x\n",
                                batostr(&bt_sk(sk)->src), batostr(&bt_sk(sk)->dst),
-                               sk->sk_state, pi->psm, pi->scid, pi->dcid, pi->imtu,
-                               pi->omtu, pi->link_mode);
+                               sk->sk_state, btohs(pi->psm), pi->scid, pi->dcid,
+                               pi->imtu, pi->omtu, pi->link_mode);
        }
 
        read_unlock_bh(&l2cap_sk_list.lock);
        }
 
        read_unlock_bh(&l2cap_sk_list.lock);
@@ -2216,7 +2225,8 @@ static int __init l2cap_init(void)
                goto error;
        }
 
                goto error;
        }
 
-       class_create_file(bt_class, &class_attr_l2cap);
+       if (class_create_file(bt_class, &class_attr_l2cap) < 0)
+               BT_ERR("Failed to create L2CAP info file");
 
        BT_INFO("L2CAP ver %s", VERSION);
        BT_INFO("L2CAP socket layer initialized");
 
        BT_INFO("L2CAP ver %s", VERSION);
        BT_INFO("L2CAP socket layer initialized");