* Sniff mode patch V2
@ 2008-09-14 20:08 Fabien Chevalier
0 siblings, 0 replies; only message in thread
From: Fabien Chevalier @ 2008-09-14 20:08 UTC (permalink / raw)
To: linux-bluetooth
[-- Attachment #1: Type: text/plain, Size: 398 bytes --]
Hi Marcel,
I spend most of the day reworking the sniff mode patch.
I implemented both L2CAP and RFCOMM, and tested those two. They both
seem to work.
The layering violation is gone.
The setting is propagated from a server socket to its children.
I think i've seen the end of your first round of comments ;-)
Could you please review this patch and tell me what needs fixing ?
Regards,
Fabien
[-- Attachment #2: 0001-Sniff-mode-fixes-V2.patch --]
[-- Type: text/x-patch, Size: 12311 bytes --]
>>From 1252afa5d458cd4782ee767ff1e487a6ce56c964 Mon Sep 17 00:00:00 2001
From: Fabien Chevalier <fabchevalier@free.fr>
Date: Sun, 14 Sep 2008 20:52:08 +0200
Subject: [PATCH] Sniff mode fixes V2.
* Introduces L2CAP_FORCE_ACTIVE_MODE and RFCOMM_FORCE_ACTIVE_MODE.
* Support for RFCOMM and L2CAP.
* Setting is now inherited on child sockets created through accept()
---
include/net/bluetooth/hci_core.h | 3 ++-
include/net/bluetooth/l2cap.h | 5 +++++
include/net/bluetooth/rfcomm.h | 3 +++
net/bluetooth/hci_conn.c | 6 +++++-
net/bluetooth/hci_core.c | 4 +++-
net/bluetooth/l2cap.c | 38 ++++++++++++++++++++++++++++++++------
net/bluetooth/rfcomm/core.c | 13 +++++++++----
net/bluetooth/rfcomm/sock.c | 32 ++++++++++++++++++++++++++++++--
8 files changed, 89 insertions(+), 15 deletions(-)
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 46a43b7..95f113e 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -170,6 +170,7 @@ struct hci_conn {
__u32 link_mode;
__u8 auth_type;
__u8 power_save;
+ __u8 force_active_mode;
unsigned long pend;
unsigned int sent;
@@ -631,7 +632,7 @@ int hci_register_notifier(struct notifier_block *nb);
int hci_unregister_notifier(struct notifier_block *nb);
int hci_send_cmd(struct hci_dev *hdev, __u16 opcode, __u32 plen, void *param);
-int hci_send_acl(struct hci_conn *conn, struct sk_buff *skb, __u16 flags);
+int hci_send_acl(struct hci_conn *conn, struct sk_buff *skb, int force_active_mode, __u16 flags);
int hci_send_sco(struct hci_conn *conn, struct sk_buff *skb);
void *hci_sent_cmd_data(struct hci_dev *hdev, __u16 opcode);
diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
index 73e115b..d13f586 100644
--- a/include/net/bluetooth/l2cap.h
+++ b/include/net/bluetooth/l2cap.h
@@ -62,6 +62,8 @@ struct l2cap_conninfo {
#define L2CAP_LM_RELIABLE 0x0010
#define L2CAP_LM_SECURE 0x0020
+#define L2CAP_FORCE_ACTIVE_MODE 0x04
+
/* L2CAP command codes */
#define L2CAP_COMMAND_REJ 0x01
#define L2CAP_CONN_REQ 0x02
@@ -210,6 +212,8 @@ struct l2cap_conn {
__u8 info_state;
__u8 info_ident;
+ int force_active_mode;
+
struct timer_list info_timer;
spinlock_t lock;
@@ -239,6 +243,7 @@ struct l2cap_pinfo {
__u16 flush_to;
__u32 link_mode;
+ int force_active_mode;
__u8 conf_req[64];
__u8 conf_len;
diff --git a/include/net/bluetooth/rfcomm.h b/include/net/bluetooth/rfcomm.h
index 4dc8d92..61bf1cf 100644
--- a/include/net/bluetooth/rfcomm.h
+++ b/include/net/bluetooth/rfcomm.h
@@ -185,6 +185,7 @@ struct rfcomm_dlc {
u8 out;
u32 link_mode;
+ int force_active_mode;
uint mtu;
uint cfc;
@@ -298,6 +299,8 @@ struct rfcomm_conninfo {
#define RFCOMM_LM_RELIABLE 0x0010
#define RFCOMM_LM_SECURE 0x0020
+#define RFCOMM_FORCE_ACTIVE_MODE 0x04
+
#define rfcomm_pi(sk) ((struct rfcomm_pinfo *) sk)
struct rfcomm_pinfo {
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
index b700242..a7feebd 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -214,6 +214,7 @@ struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst)
conn->state = BT_OPEN;
conn->power_save = 1;
+ conn->force_active_mode = 0;
switch (type) {
case ACL_LINK:
@@ -479,9 +480,12 @@ void hci_conn_enter_active_mode(struct hci_conn *conn)
if (test_bit(HCI_RAW, &hdev->flags))
return;
- if (conn->mode != HCI_CM_SNIFF || !conn->power_save)
+ if (conn->mode != HCI_CM_SNIFF)
goto timer;
+ if (!conn->power_save && !conn->force_active_mode)
+ goto timer;
+
if (!test_and_set_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend)) {
struct hci_cp_exit_sniff_mode cp;
cp.handle = cpu_to_le16(conn->handle);
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index f5b21cb..ec4b1ff 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -1193,7 +1193,7 @@ static void hci_add_acl_hdr(struct sk_buff *skb, __u16 handle, __u16 flags)
hdr->dlen = cpu_to_le16(len);
}
-int hci_send_acl(struct hci_conn *conn, struct sk_buff *skb, __u16 flags)
+int hci_send_acl(struct hci_conn *conn, struct sk_buff *skb, int force_active_mode, __u16 flags)
{
struct hci_dev *hdev = conn->hdev;
struct sk_buff *list;
@@ -1234,6 +1234,8 @@ int hci_send_acl(struct hci_conn *conn, struct sk_buff *skb, __u16 flags)
spin_unlock_bh(&conn->data_q.lock);
}
+ conn->force_active_mode = force_active_mode;
+
hci_sched_tx(hdev);
return 0;
}
diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c
index 9610a9c..7d422e9 100644
--- a/net/bluetooth/l2cap.c
+++ b/net/bluetooth/l2cap.c
@@ -304,12 +304,12 @@ static inline int l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16
{
struct sk_buff *skb = l2cap_build_cmd(conn, code, ident, len, data);
- BT_DBG("code 0x%2.2x", code);
+ BT_DBG("code 0x%2.2x active_mode %d ", code, conn->force_active_mode);
if (!skb)
return -ENOMEM;
- return hci_send_acl(conn->hcon, skb, 0);
+ return hci_send_acl(conn->hcon, skb, conn->force_active_mode, 0);
}
static void l2cap_do_start(struct sock *sk)
@@ -661,10 +661,13 @@ static void l2cap_sock_init(struct sock *sk, struct sock *parent)
pi->imtu = l2cap_pi(parent)->imtu;
pi->omtu = l2cap_pi(parent)->omtu;
pi->link_mode = l2cap_pi(parent)->link_mode;
+ pi->force_active_mode =
+ l2cap_pi(parent)->force_active_mode;
} else {
pi->imtu = L2CAP_DEFAULT_MTU;
pi->omtu = 0;
pi->link_mode = 0;
+ pi->force_active_mode = 0;
}
/* Default config options */
@@ -818,6 +821,8 @@ static int l2cap_do_connect(struct sock *sk)
/* Update source addr of the socket */
bacpy(src, conn->src);
+
+ conn->force_active_mode = l2cap_pi(sk)->force_active_mode;
l2cap_chan_add(conn, sk, NULL);
@@ -1021,7 +1026,7 @@ static inline int l2cap_do_send(struct sock *sk, struct msghdr *msg, int len)
int err, hlen, count, sent=0;
struct l2cap_hdr *lh;
- BT_DBG("sk %p len %d", sk, len);
+ BT_DBG("sk %p len %d active_mode %d", sk, len, conn->force_active_mode);
/* First fragment (with L2CAP header) */
if (sk->sk_type == SOCK_DGRAM)
@@ -1072,7 +1077,7 @@ static inline int l2cap_do_send(struct sock *sk, struct msghdr *msg, int len)
frag = &(*frag)->next;
}
- if ((err = hci_send_acl(conn->hcon, skb, 0)) < 0)
+ if ((err = hci_send_acl(conn->hcon, skb, l2cap_pi(sk)->force_active_mode, 0)) < 0)
goto fail;
return sent;
@@ -1148,6 +1153,20 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, ch
l2cap_pi(sk)->link_mode = opt;
break;
+ case L2CAP_FORCE_ACTIVE_MODE:
+ if (get_user(opt, (u32 __user *) optval)) {
+ err = -EFAULT;
+ break;
+ }
+
+ l2cap_pi(sk)->force_active_mode = opt;
+
+ if (sk->sk_state == BT_CONNECTED) {
+ l2cap_pi(sk)->conn->force_active_mode = opt;
+ }
+
+ break;
+
default:
err = -ENOPROTOOPT;
break;
@@ -1204,6 +1223,12 @@ static int l2cap_sock_getsockopt(struct socket *sock, int level, int optname, ch
break;
+ case L2CAP_FORCE_ACTIVE_MODE:
+ if (put_user(l2cap_pi(sk)->force_active_mode,
+ (u32 __user *) optval))
+ err = -EFAULT;
+ break;
+
default:
err = -ENOPROTOOPT;
break;
@@ -2429,10 +2454,11 @@ static ssize_t l2cap_sysfs_show(struct class *dev, char *buf)
sk_for_each(sk, node, &l2cap_sk_list.head) {
struct l2cap_pinfo *pi = l2cap_pi(sk);
- str += sprintf(str, "%s %s %d %d 0x%4.4x 0x%4.4x %d %d 0x%x\n",
+ str += sprintf(str, "%s %s %d %d 0x%4.4x 0x%4.4x %d %d 0x%x %d\n",
batostr(&bt_sk(sk)->src), batostr(&bt_sk(sk)->dst),
sk->sk_state, btohs(pi->psm), pi->scid, pi->dcid,
- pi->imtu, pi->omtu, pi->link_mode);
+ pi->imtu, pi->omtu, pi->link_mode,
+ pi->force_active_mode);
}
read_unlock_bh(&l2cap_sk_list.lock);
diff --git a/net/bluetooth/rfcomm/core.c b/net/bluetooth/rfcomm/core.c
index ba537fa..888b431 100644
--- a/net/bluetooth/rfcomm/core.c
+++ b/net/bluetooth/rfcomm/core.c
@@ -80,7 +80,7 @@ static void rfcomm_make_uih(struct sk_buff *skb, u8 addr);
static void rfcomm_process_connect(struct rfcomm_session *s);
-static struct rfcomm_session *rfcomm_session_create(bdaddr_t *src, bdaddr_t *dst, int *err);
+static struct rfcomm_session *rfcomm_session_create(bdaddr_t *src, bdaddr_t *dst, int force_active_mode, int *err);
static struct rfcomm_session *rfcomm_session_get(bdaddr_t *src, bdaddr_t *dst);
static void rfcomm_session_del(struct rfcomm_session *s);
@@ -367,7 +367,7 @@ static int __rfcomm_dlc_open(struct rfcomm_dlc *d, bdaddr_t *src, bdaddr_t *dst,
s = rfcomm_session_get(src, dst);
if (!s) {
- s = rfcomm_session_create(src, dst, &err);
+ s = rfcomm_session_create(src, dst, d->force_active_mode, &err);
if (!s)
return err;
}
@@ -625,19 +625,24 @@ static void rfcomm_session_close(struct rfcomm_session *s, int err)
rfcomm_session_put(s);
}
-static struct rfcomm_session *rfcomm_session_create(bdaddr_t *src, bdaddr_t *dst, int *err)
+static struct rfcomm_session *rfcomm_session_create(bdaddr_t *src, bdaddr_t *dst, int force_active_mode, int *err)
{
struct rfcomm_session *s = NULL;
struct sockaddr_l2 addr;
struct socket *sock;
struct sock *sk;
- BT_DBG("%s %s", batostr(src), batostr(dst));
+ BT_DBG("%s %s %d", batostr(src), batostr(dst), force_active_mode);
*err = rfcomm_l2sock_create(&sock);
if (*err < 0)
return NULL;
+ *err = kernel_setsockopt(sock, SOL_BLUETOOTH, L2CAP_FORCE_ACTIVE_MODE,
+ (void *) &force_active_mode, sizeof(force_active_mode));
+ if (*err < 0)
+ goto failed;
+
bacpy(&addr.l2_bdaddr, src);
addr.l2_family = AF_BLUETOOTH;
addr.l2_psm = 0;
diff --git a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c
index 8a972b6..f6a48e5 100644
--- a/net/bluetooth/rfcomm/sock.c
+++ b/net/bluetooth/rfcomm/sock.c
@@ -267,8 +267,11 @@ static void rfcomm_sock_init(struct sock *sk, struct sock *parent)
if (parent) {
sk->sk_type = parent->sk_type;
pi->link_mode = rfcomm_pi(parent)->link_mode;
+ pi->dlc->force_active_mode =
+ rfcomm_pi(parent)->dlc->force_active_mode;
} else {
pi->link_mode = 0;
+ pi->dlc->force_active_mode = 0;
}
pi->dlc->link_mode = pi->link_mode;
@@ -735,6 +738,15 @@ static int rfcomm_sock_setsockopt(struct socket *sock, int level, int optname, c
rfcomm_pi(sk)->link_mode = opt;
break;
+ case RFCOMM_FORCE_ACTIVE_MODE:
+ if (get_user(opt, (u32 __user *) optval)) {
+ err = -EFAULT;
+ break;
+ }
+
+ rfcomm_pi(sk)->dlc->force_active_mode = opt;
+ break;
+
default:
err = -ENOPROTOOPT;
break;
@@ -781,6 +793,12 @@ static int rfcomm_sock_getsockopt(struct socket *sock, int level, int optname, c
break;
+ case RFCOMM_FORCE_ACTIVE_MODE:
+ if (put_user(rfcomm_pi(sk)->dlc->force_active_mode,
+ (u32 __user *) optval))
+ err = -EFAULT;
+ break;
+
default:
err = -ENOPROTOOPT;
break;
@@ -859,6 +877,8 @@ int rfcomm_connect_ind(struct rfcomm_session *s, u8 channel, struct rfcomm_dlc *
struct sock *sk, *parent;
bdaddr_t src, dst;
int result = 0;
+ int err;
+ int force_active_mode;
BT_DBG("session %p channel %d", s, channel);
@@ -869,6 +889,13 @@ int rfcomm_connect_ind(struct rfcomm_session *s, u8 channel, struct rfcomm_dlc *
if (!parent)
return 0;
+ /* Propagate setting to children */
+ force_active_mode = rfcomm_pi(parent)->dlc->force_active_mode;
+ err = kernel_setsockopt(s->sock, SOL_BLUETOOTH, L2CAP_FORCE_ACTIVE_MODE,
+ (void *) &force_active_mode, sizeof(force_active_mode));
+ if (err < 0)
+ goto done;
+
/* Check for backlog size */
if (sk_acceptq_is_full(parent)) {
BT_DBG("backlog full %d", parent->sk_ack_backlog);
@@ -905,9 +932,10 @@ static ssize_t rfcomm_sock_sysfs_show(struct class *dev, char *buf)
read_lock_bh(&rfcomm_sk_list.lock);
sk_for_each(sk, node, &rfcomm_sk_list.head) {
- str += sprintf(str, "%s %s %d %d\n",
+ str += sprintf(str, "%s %s %d %d %d\n",
batostr(&bt_sk(sk)->src), batostr(&bt_sk(sk)->dst),
- sk->sk_state, rfcomm_pi(sk)->channel);
+ sk->sk_state, rfcomm_pi(sk)->channel,
+ rfcomm_pi(sk)->dlc->force_active_mode);
}
read_unlock_bh(&rfcomm_sk_list.lock);
--
1.5.6.5
^ permalink raw reply related [flat|nested] only message in thread
only message in thread, other threads:[~2008-09-14 20:08 UTC | newest]
Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-09-14 20:08 Sniff mode patch V2 Fabien Chevalier
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox