aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarcel Holtmann <marcel@holtmann.org>2009-01-15 21:52:16 +0100
committerMarcel Holtmann <marcel@holtmann.org>2009-02-27 06:14:23 +0100
commitc4f912e155504e94dd4f3d63c378dab0ff03dbda (patch)
treedb544bdd0dfc8ca890193a29b161b551f20f543c
parentd58daf42d29a3a4a4d4be46cf47ceee096789680 (diff)
Bluetooth: Add global deferred socket parameter
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>
-rw-r--r--include/net/bluetooth/bluetooth.h3
-rw-r--r--net/bluetooth/af_bluetooth.c8
2 files changed, 9 insertions, 2 deletions
diff --git a/include/net/bluetooth/bluetooth.h b/include/net/bluetooth/bluetooth.h
index a04f8463ac7..847e9e6df08 100644
--- a/include/net/bluetooth/bluetooth.h
+++ b/include/net/bluetooth/bluetooth.h
@@ -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 {
diff --git a/net/bluetooth/af_bluetooth.c b/net/bluetooth/af_bluetooth.c
index 744ed3f07ef..7c0031ff8cf 100644
--- a/net/bluetooth/af_bluetooth.c
+++ b/net/bluetooth/af_bluetooth.c
@@ -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)