Fedora kernel-2.6.17-1.2142_FC4 patched with stable patch-2.6.17.4-vs2.0.2-rc26.diff
[linux-2.6.git] / net / bluetooth / l2cap.c
index ff8d310..f6b4a80 100644 (file)
@@ -28,9 +28,9 @@
 #include <linux/module.h>
 
 #include <linux/types.h>
+#include <linux/capability.h>
 #include <linux/errno.h>
 #include <linux/kernel.h>
-#include <linux/major.h>
 #include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/poll.h>
@@ -39,9 +39,8 @@
 #include <linux/interrupt.h>
 #include <linux/socket.h>
 #include <linux/skbuff.h>
-#include <linux/proc_fs.h>
-#include <linux/seq_file.h>
 #include <linux/list.h>
+#include <linux/device.h>
 #include <net/sock.h>
 
 #include <asm/system.h>
@@ -57,9 +56,9 @@
 #define BT_DBG(D...)
 #endif
 
-#define VERSION "2.7"
+#define VERSION "2.8"
 
-static struct proto_ops l2cap_sock_ops;
+static const struct proto_ops l2cap_sock_ops;
 
 static struct bt_sock_list l2cap_sk_list = {
        .lock = RW_LOCK_UNLOCKED
@@ -264,9 +263,6 @@ static void l2cap_sock_destruct(struct sock *sk)
 
        skb_queue_purge(&sk->sk_receive_queue);
        skb_queue_purge(&sk->sk_write_queue);
-
-       if (sk->sk_protinfo)
-               kfree(sk->sk_protinfo);
 }
 
 static void l2cap_sock_cleanup_listen(struct sock *parent)
@@ -280,7 +276,7 @@ static void l2cap_sock_cleanup_listen(struct sock *parent)
                l2cap_sock_close(sk);
 
        parent->sk_state  = BT_CLOSED;
-       parent->sk_zapped = 1;
+       sock_set_flag(parent, SOCK_ZAPPED);
 }
 
 /* Kill socket (only if zapped and orphan)
@@ -288,7 +284,7 @@ static void l2cap_sock_cleanup_listen(struct sock *parent)
  */
 static void l2cap_sock_kill(struct sock *sk)
 {
-       if (!sk->sk_zapped || sk->sk_socket)
+       if (!sock_flag(sk, SOCK_ZAPPED) || sk->sk_socket)
                return;
 
        BT_DBG("sk %p state %d", sk, sk->sk_state);
@@ -333,7 +329,7 @@ static void __l2cap_sock_close(struct sock *sk, int reason)
                break;
 
        default:
-               sk->sk_zapped = 1;
+               sock_set_flag(sk, SOCK_ZAPPED);
                break;
        }
 }
@@ -370,19 +366,28 @@ static void l2cap_sock_init(struct sock *sk, struct sock *parent)
        pi->flush_to = L2CAP_DEFAULT_FLUSH_TO;
 }
 
-static struct sock *l2cap_sock_alloc(struct socket *sock, int proto, int prio)
+static struct proto l2cap_proto = {
+       .name           = "L2CAP",
+       .owner          = THIS_MODULE,
+       .obj_size       = sizeof(struct l2cap_pinfo)
+};
+
+static struct sock *l2cap_sock_alloc(struct socket *sock, int proto, gfp_t prio)
 {
        struct sock *sk;
 
-       sk = bt_sock_alloc(sock, proto, sizeof(struct l2cap_pinfo), prio);
+       sk = sk_alloc(PF_BLUETOOTH, prio, &l2cap_proto, 1);
        if (!sk)
                return NULL;
 
-       sk_set_owner(sk, THIS_MODULE);
+       sock_init_data(sock, sk);
+       INIT_LIST_HEAD(&bt_sk(sk)->accept_q);
 
        sk->sk_destruct = l2cap_sock_destruct;
        sk->sk_sndtimeo = L2CAP_CONN_TIMEOUT;
 
+       sock_reset_flag(sk, SOCK_ZAPPED);
+
        sk->sk_protocol = proto;
        sk->sk_state    = BT_OPEN;
 
@@ -763,8 +768,9 @@ static int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct ms
 
        BT_DBG("sock %p, sk %p", sock, sk);
 
-       if (sk->sk_err)
-               return sock_error(sk);
+       err = sock_error(sk);
+       if (err)
+               return err;
 
        if (msg->msg_flags & MSG_OOB)
                return -EOPNOTSUPP;
@@ -1062,7 +1068,7 @@ static void l2cap_chan_del(struct sock *sk, int err)
        }
 
        sk->sk_state  = BT_CLOSED;
-       sk->sk_zapped = 1;
+       sock_set_flag(sk, SOCK_ZAPPED);
 
        if (err)
                sk->sk_err = err;
@@ -1410,7 +1416,7 @@ static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hd
        result = L2CAP_CR_NO_MEM;
 
        /* Check for backlog size */
-       if (parent->sk_ack_backlog > parent->sk_max_ack_backlog) {
+       if (sk_acceptq_is_full(parent)) {
                BT_DBG("backlog full %d", parent->sk_ack_backlog); 
                goto response;
        }
@@ -1424,7 +1430,7 @@ static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hd
        /* Check if we already have channel with that dcid */
        if (__l2cap_get_chan_by_dcid(list, scid)) {
                write_unlock(&list->lock);
-               sk->sk_zapped = 1;
+               sock_set_flag(sk, SOCK_ZAPPED);
                l2cap_sock_kill(sk);
                goto response;
        }
@@ -2132,96 +2138,31 @@ drop:
        return 0;
 }
 
-/* ---- Proc fs support ---- */
-#ifdef CONFIG_PROC_FS
-static void *l2cap_seq_start(struct seq_file *seq, loff_t *pos)
+static ssize_t l2cap_sysfs_show(struct class *dev, char *buf)
 {
        struct sock *sk;
        struct hlist_node *node;
-       loff_t l = *pos;
+       char *str = buf;
 
        read_lock_bh(&l2cap_sk_list.lock);
 
-       sk_for_each(sk, node, &l2cap_sk_list.head)
-               if (!l--)
-                       goto found;
-       sk = NULL;
-found:
-       return sk;
-}
+       sk_for_each(sk, node, &l2cap_sk_list.head) {
+               struct l2cap_pinfo *pi = l2cap_pi(sk);
 
-static void *l2cap_seq_next(struct seq_file *seq, void *e, loff_t *pos)
-{
-       (*pos)++;
-       return sk_next(e);
-}
+               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);
+       }
 
-static void l2cap_seq_stop(struct seq_file *seq, void *e)
-{
        read_unlock_bh(&l2cap_sk_list.lock);
-}
-
-static int  l2cap_seq_show(struct seq_file *seq, void *e)
-{
-       struct sock *sk = e;
-       struct l2cap_pinfo *pi = l2cap_pi(sk);
 
-       seq_printf(seq, "%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);
-       return 0;
+       return (str - buf);
 }
 
-static struct seq_operations l2cap_seq_ops = {
-       .start  = l2cap_seq_start,
-       .next   = l2cap_seq_next,
-       .stop   = l2cap_seq_stop,
-       .show   = l2cap_seq_show 
-};
-
-static int l2cap_seq_open(struct inode *inode, struct file *file)
-{
-       return seq_open(file, &l2cap_seq_ops);
-}
+static CLASS_ATTR(l2cap, S_IRUGO, l2cap_sysfs_show, NULL);
 
-static struct file_operations l2cap_seq_fops = {
-       .owner          = THIS_MODULE,
-       .open           = l2cap_seq_open,
-       .read           = seq_read,
-       .llseek         = seq_lseek,
-       .release        = seq_release,
-};
-
-static int __init l2cap_proc_init(void)
-{
-       struct proc_dir_entry *p = create_proc_entry("l2cap", S_IRUGO, proc_bt);
-       if (!p)
-               return -ENOMEM;
-       p->owner     = THIS_MODULE;
-       p->proc_fops = &l2cap_seq_fops;
-       return 0;
-}
-
-static void __exit l2cap_proc_cleanup(void)
-{
-       remove_proc_entry("l2cap", proc_bt);
-}
-
-#else /* CONFIG_PROC_FS */
-
-static int __init l2cap_proc_init(void)
-{
-       return 0;
-}
-
-static void __exit l2cap_proc_cleanup(void)
-{
-       return;
-}
-#endif /* CONFIG_PROC_FS */
-
-static struct proto_ops l2cap_sock_ops = {
+static const struct proto_ops l2cap_sock_ops = {
        .family         = PF_BLUETOOTH,
        .owner          = THIS_MODULE,
        .release        = l2cap_sock_release,
@@ -2262,34 +2203,46 @@ static int __init l2cap_init(void)
 {
        int err;
 
-       if ((err = bt_sock_register(BTPROTO_L2CAP, &l2cap_sock_family_ops))) {
-               BT_ERR("L2CAP socket registration failed");
+       err = proto_register(&l2cap_proto, 0);
+       if (err < 0)
                return err;
+
+       err = bt_sock_register(BTPROTO_L2CAP, &l2cap_sock_family_ops);
+       if (err < 0) {
+               BT_ERR("L2CAP socket registration failed");
+               goto error;
        }
 
-       if ((err = hci_register_proto(&l2cap_hci_proto))) {
+       err = hci_register_proto(&l2cap_hci_proto);
+       if (err < 0) {
                BT_ERR("L2CAP protocol registration failed");
-               return err;
+               bt_sock_unregister(BTPROTO_L2CAP);
+               goto error;
        }
 
-       l2cap_proc_init();
+       class_create_file(&bt_class, &class_attr_l2cap);
 
        BT_INFO("L2CAP ver %s", VERSION);
        BT_INFO("L2CAP socket layer initialized");
 
        return 0;
+
+error:
+       proto_unregister(&l2cap_proto);
+       return err;
 }
 
 static void __exit l2cap_exit(void)
 {
-       l2cap_proc_cleanup();
+       class_remove_file(&bt_class, &class_attr_l2cap);
 
-       /* Unregister socket and protocol */
-       if (bt_sock_unregister(BTPROTO_L2CAP))
+       if (bt_sock_unregister(BTPROTO_L2CAP) < 0)
                BT_ERR("L2CAP socket unregistration failed");
 
-       if (hci_unregister_proto(&l2cap_hci_proto))
+       if (hci_unregister_proto(&l2cap_hci_proto) < 0)
                BT_ERR("L2CAP protocol unregistration failed");
+
+       proto_unregister(&l2cap_proto);
 }
 
 void l2cap_load(void)