Bluetooth: Add global deferred socket parameter
authorMarcel Holtmann <marcel@holtmann.org>
Thu, 15 Jan 2009 20:52:16 +0000 (21:52 +0100)
committerMarcel Holtmann <marcel@holtmann.org>
Fri, 27 Feb 2009 05:14:23 +0000 (06:14 +0100)
The L2CAP and RFCOMM applications require support for authorization
and the ability of rejecting incoming connection requests. The socket
interface is not really able to support this.

This patch does the ground work for a socket option to defer connection
setup. Setting this option allows calling of accept() and then the
first read() will trigger the final connection setup. Calling close()
would reject the connection.

Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
include/net/bluetooth/bluetooth.h
net/bluetooth/af_bluetooth.c

index a04f8463ac7eec813cba0f9dfcb23e0e484036a5..847e9e6df08b149094c6e684c7eb4ceb237d18ba 100644 (file)
@@ -53,6 +53,8 @@
 #define SOL_SCO                17
 #define SOL_RFCOMM     18
 
+#define BT_DEFER_SETUP 7
+
 #define BT_INFO(fmt, arg...) printk(KERN_INFO "Bluetooth: " fmt "\n" , ## arg)
 #define BT_ERR(fmt, arg...)  printk(KERN_ERR "%s: " fmt "\n" , __func__ , ## arg)
 #define BT_DBG(fmt, arg...)  pr_debug("%s: " fmt "\n" , __func__ , ## arg)
@@ -108,6 +110,7 @@ struct bt_sock {
        bdaddr_t    dst;
        struct list_head accept_q;
        struct sock *parent;
+       u32 defer_setup;
 };
 
 struct bt_sock_list {
index 744ed3f07ef38374f6c1b0480d56954d4cf77eac..7c0031ff8cfbbc6b672880f445d33bf6632e8256 100644 (file)
@@ -217,7 +217,8 @@ struct sock *bt_accept_dequeue(struct sock *parent, struct socket *newsock)
                        continue;
                }
 
-               if (sk->sk_state == BT_CONNECTED || !newsock) {
+               if (sk->sk_state == BT_CONNECTED || !newsock ||
+                                               bt_sk(parent)->defer_setup) {
                        bt_accept_unlink(sk);
                        if (newsock)
                                sock_graft(sk, newsock);
@@ -232,7 +233,7 @@ struct sock *bt_accept_dequeue(struct sock *parent, struct socket *newsock)
 EXPORT_SYMBOL(bt_accept_dequeue);
 
 int bt_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
-       struct msghdr *msg, size_t len, int flags)
+                               struct msghdr *msg, size_t len, int flags)
 {
        int noblock = flags & MSG_DONTWAIT;
        struct sock *sk = sock->sk;
@@ -275,6 +276,9 @@ static inline unsigned int bt_accept_poll(struct sock *parent)
        struct list_head *p, *n;
        struct sock *sk;
 
+       if (bt_sk(parent)->defer_setup)
+               return POLLIN | POLLRDNORM;
+
        list_for_each_safe(p, n, &bt_sk(parent)->accept_q) {
                sk = (struct sock *) list_entry(p, struct bt_sock, accept_q);
                if (sk->sk_state == BT_CONNECTED)