Commit 1317c324 authored by Marcel Holtmann's avatar Marcel Holtmann Committed by Marcel Holtmann

[Bluetooth] Fix resetting to default filters

The problem is that after a successful connection between the Windows
Bluetooth stack and the Linux Bluez stack, no packets from the device
ever reach the PC running Windows XP Service Pack 2. That is, a ping
from the PC never receives a response, and a ping from BlueZ never
reaches the PC. Linux packet statistics show that the PC packets are
received, but all return traffic seems to be routed over the loopback
interface.

Immediately after creating the BNEP connection with BlueZ, the Windows
Bluetooth stack sends a BNEP_FILTER_NET_TYPE_SET_MSG with an effective
length of zero. BlueZ interprets this message to mean that no filter
ranges should be allowed. The code zeros the first entry in the filter
list, which is than interpreted as meaning that no ranges of acceptable
packets are available. This interpretation is wrong and leads to all
packets being rejected by BNEP.

The Bluetooth BNEP specification clearly states the following:

The length (in octets) of this message is 4+4*N, where N is the number
of disjoint ranges of Networking protocol types that form the complete
set. Note that N=0 (empty set) denotes a reset to default filters (if
any) supported by the remote device.
Signed-off-by: default avatarMarcel Holtmann <marcel@holtmann.org>
parent c8f53798
...@@ -61,7 +61,7 @@ ...@@ -61,7 +61,7 @@
#define BT_DBG(D...) #define BT_DBG(D...)
#endif #endif
#define VERSION "1.0" #define VERSION "1.2"
static LIST_HEAD(bnep_session_list); static LIST_HEAD(bnep_session_list);
static DECLARE_RWSEM(bnep_session_sem); static DECLARE_RWSEM(bnep_session_sem);
...@@ -115,6 +115,21 @@ static int bnep_send_rsp(struct bnep_session *s, u8 ctrl, u16 resp) ...@@ -115,6 +115,21 @@ static int bnep_send_rsp(struct bnep_session *s, u8 ctrl, u16 resp)
return bnep_send(s, &rsp, sizeof(rsp)); return bnep_send(s, &rsp, sizeof(rsp));
} }
#ifdef CONFIG_BT_BNEP_PROTO_FILTER
static inline void bnep_set_default_proto_filter(struct bnep_session *s)
{
/* (IPv4, ARP) */
s->proto_filter[0].start = htons(0x0800);
s->proto_filter[0].end = htons(0x0806);
/* (RARP, AppleTalk) */
s->proto_filter[1].start = htons(0x8035);
s->proto_filter[1].end = htons(0x80F3);
/* (IPX, IPv6) */
s->proto_filter[2].start = htons(0x8137);
s->proto_filter[2].end = htons(0x86DD);
}
#endif
static int bnep_ctrl_set_netfilter(struct bnep_session *s, u16 *data, int len) static int bnep_ctrl_set_netfilter(struct bnep_session *s, u16 *data, int len)
{ {
int n; int n;
...@@ -143,9 +158,13 @@ static int bnep_ctrl_set_netfilter(struct bnep_session *s, u16 *data, int len) ...@@ -143,9 +158,13 @@ static int bnep_ctrl_set_netfilter(struct bnep_session *s, u16 *data, int len)
BT_DBG("proto filter start %d end %d", BT_DBG("proto filter start %d end %d",
f[i].start, f[i].end); f[i].start, f[i].end);
} }
if (i < BNEP_MAX_PROTO_FILTERS) if (i < BNEP_MAX_PROTO_FILTERS)
memset(f + i, 0, sizeof(*f)); memset(f + i, 0, sizeof(*f));
if (n == 0)
bnep_set_default_proto_filter(s);
bnep_send_rsp(s, BNEP_FILTER_NET_TYPE_RSP, BNEP_SUCCESS); bnep_send_rsp(s, BNEP_FILTER_NET_TYPE_RSP, BNEP_SUCCESS);
} else { } else {
bnep_send_rsp(s, BNEP_FILTER_NET_TYPE_RSP, BNEP_FILTER_LIMIT_REACHED); bnep_send_rsp(s, BNEP_FILTER_NET_TYPE_RSP, BNEP_FILTER_LIMIT_REACHED);
...@@ -550,21 +569,12 @@ int bnep_add_connection(struct bnep_connadd_req *req, struct socket *sock) ...@@ -550,21 +569,12 @@ int bnep_add_connection(struct bnep_connadd_req *req, struct socket *sock)
/* Set default mc filter */ /* Set default mc filter */
set_bit(bnep_mc_hash(dev->broadcast), (ulong *) &s->mc_filter); set_bit(bnep_mc_hash(dev->broadcast), (ulong *) &s->mc_filter);
#endif #endif
#ifdef CONFIG_BT_BNEP_PROTO_FILTER #ifdef CONFIG_BT_BNEP_PROTO_FILTER
/* Set default protocol filter */ /* Set default protocol filter */
bnep_set_default_proto_filter(s);
/* (IPv4, ARP) */
s->proto_filter[0].start = htons(0x0800);
s->proto_filter[0].end = htons(0x0806);
/* (RARP, AppleTalk) */
s->proto_filter[1].start = htons(0x8035);
s->proto_filter[1].end = htons(0x80F3);
/* (IPX, IPv6) */
s->proto_filter[2].start = htons(0x8137);
s->proto_filter[2].end = htons(0x86DD);
#endif #endif
err = register_netdev(dev); err = register_netdev(dev);
if (err) { if (err) {
goto failed; goto failed;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment