summaryrefslogtreecommitdiffstats
path: root/net/bluetooth/bnep
diff options
context:
space:
mode:
authorGrzegorz Kolodziejczyk <grzegorz.kolodziejczyk@tieto.com>2015-04-03 12:14:54 +0200
committerMarcel Holtmann <marcel@holtmann.org>2015-04-03 23:21:34 +0200
commitbf8b9a9cb77b14e37a8bc925be5db7bfd54d69a8 (patch)
tree5900f4ea20c1ef3a10c9cf30dccd9f3baa366e36 /net/bluetooth/bnep
parent0477e2e868ceead7fd96218e1a062e01631ce717 (diff)
downloadop-kernel-dev-bf8b9a9cb77b14e37a8bc925be5db7bfd54d69a8.zip
op-kernel-dev-bf8b9a9cb77b14e37a8bc925be5db7bfd54d69a8.tar.gz
Bluetooth: bnep: Add support to extended headers of control frames
Handling extended headers of control frames is required BNEP functionality. This patch refractor bnep rx frame handling function. Extended header for control frames shouldn't be omitted as it was previously done. Every control frame should be checked if it contains extended header and then every extension should be parsed separately. Signed-off-by: Grzegorz Kolodziejczyk <grzegorz.kolodziejczyk@tieto.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
Diffstat (limited to 'net/bluetooth/bnep')
-rw-r--r--net/bluetooth/bnep/core.c46
1 files changed, 36 insertions, 10 deletions
diff --git a/net/bluetooth/bnep/core.c b/net/bluetooth/bnep/core.c
index 5cf5fbd..0ee6f6d 100644
--- a/net/bluetooth/bnep/core.c
+++ b/net/bluetooth/bnep/core.c
@@ -292,29 +292,55 @@ static int bnep_rx_frame(struct bnep_session *s, struct sk_buff *skb)
{
struct net_device *dev = s->dev;
struct sk_buff *nskb;
- u8 type;
+ u8 type, ctrl_type;
dev->stats.rx_bytes += skb->len;
type = *(u8 *) skb->data;
skb_pull(skb, 1);
+ ctrl_type = *(u8 *)skb->data;
if ((type & BNEP_TYPE_MASK) >= sizeof(__bnep_rx_hlen))
goto badframe;
if ((type & BNEP_TYPE_MASK) == BNEP_CONTROL) {
- bnep_rx_control(s, skb->data, skb->len);
- kfree_skb(skb);
- return 0;
- }
+ if (bnep_rx_control(s, skb->data, skb->len) < 0) {
+ dev->stats.tx_errors++;
+ kfree_skb(skb);
+ return 0;
+ }
- skb_reset_mac_header(skb);
+ if (!(type & BNEP_EXT_HEADER)) {
+ kfree_skb(skb);
+ return 0;
+ }
- /* Verify and pull out header */
- if (!skb_pull(skb, __bnep_rx_hlen[type & BNEP_TYPE_MASK]))
- goto badframe;
+ /* Verify and pull ctrl message since it's already processed */
+ switch (ctrl_type) {
+ case BNEP_SETUP_CONN_REQ:
+ /* Pull: ctrl type (1 b), len (1 b), data (len bytes) */
+ if (!skb_pull(skb, 2 + *(u8 *)(skb->data + 1) * 2))
+ goto badframe;
+ break;
+ case BNEP_FILTER_MULTI_ADDR_SET:
+ case BNEP_FILTER_NET_TYPE_SET:
+ /* Pull: ctrl type (1 b), len (2 b), data (len bytes) */
+ if (!skb_pull(skb, 3 + *(u16 *)(skb->data + 1) * 2))
+ goto badframe;
+ break;
+ default:
+ kfree_skb(skb);
+ return 0;
+ }
+ } else {
+ skb_reset_mac_header(skb);
- s->eh.h_proto = get_unaligned((__be16 *) (skb->data - 2));
+ /* Verify and pull out header */
+ if (!skb_pull(skb, __bnep_rx_hlen[type & BNEP_TYPE_MASK]))
+ goto badframe;
+
+ s->eh.h_proto = get_unaligned((__be16 *) (skb->data - 2));
+ }
if (type & BNEP_EXT_HEADER) {
if (bnep_rx_extension(s, skb) < 0)
OpenPOWER on IntegriCloud