]> git.baikalelectronics.ru Git - kernel.git/commitdiff
Bluetooth: bnep: Add support to extended headers of control frames
authorGrzegorz Kolodziejczyk <grzegorz.kolodziejczyk@tieto.com>
Fri, 3 Apr 2015 10:14:54 +0000 (12:14 +0200)
committerMarcel Holtmann <marcel@holtmann.org>
Fri, 3 Apr 2015 21:21:34 +0000 (23:21 +0200)
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>
net/bluetooth/bnep/core.c

index 5cf5fbd2908d111c0bdf683726a259df27427346..0ee6f6d9d93e153eaa20c7f11f70d3de6fb18b1a 100644 (file)
@@ -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)