aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGrzegorz Kolodziejczyk <grzegorz.kolodziejczyk@tieto.com>2015-04-03 06:14:54 -0400
committerMarcel Holtmann <marcel@holtmann.org>2015-04-03 17:21:34 -0400
commitbf8b9a9cb77b14e37a8bc925be5db7bfd54d69a8 (patch)
tree5900f4ea20c1ef3a10c9cf30dccd9f3baa366e36
parent0477e2e868ceead7fd96218e1a062e01631ce717 (diff)
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>
-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 5cf5fbd2908d..0ee6f6d9d93e 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)
292{ 292{
293 struct net_device *dev = s->dev; 293 struct net_device *dev = s->dev;
294 struct sk_buff *nskb; 294 struct sk_buff *nskb;
295 u8 type; 295 u8 type, ctrl_type;
296 296
297 dev->stats.rx_bytes += skb->len; 297 dev->stats.rx_bytes += skb->len;
298 298
299 type = *(u8 *) skb->data; 299 type = *(u8 *) skb->data;
300 skb_pull(skb, 1); 300 skb_pull(skb, 1);
301 ctrl_type = *(u8 *)skb->data;
301 302
302 if ((type & BNEP_TYPE_MASK) >= sizeof(__bnep_rx_hlen)) 303 if ((type & BNEP_TYPE_MASK) >= sizeof(__bnep_rx_hlen))
303 goto badframe; 304 goto badframe;
304 305
305 if ((type & BNEP_TYPE_MASK) == BNEP_CONTROL) { 306 if ((type & BNEP_TYPE_MASK) == BNEP_CONTROL) {
306 bnep_rx_control(s, skb->data, skb->len); 307 if (bnep_rx_control(s, skb->data, skb->len) < 0) {
307 kfree_skb(skb); 308 dev->stats.tx_errors++;
308 return 0; 309 kfree_skb(skb);
309 } 310 return 0;
311 }
310 312
311 skb_reset_mac_header(skb); 313 if (!(type & BNEP_EXT_HEADER)) {
314 kfree_skb(skb);
315 return 0;
316 }
312 317
313 /* Verify and pull out header */ 318 /* Verify and pull ctrl message since it's already processed */
314 if (!skb_pull(skb, __bnep_rx_hlen[type & BNEP_TYPE_MASK])) 319 switch (ctrl_type) {
315 goto badframe; 320 case BNEP_SETUP_CONN_REQ:
321 /* Pull: ctrl type (1 b), len (1 b), data (len bytes) */
322 if (!skb_pull(skb, 2 + *(u8 *)(skb->data + 1) * 2))
323 goto badframe;
324 break;
325 case BNEP_FILTER_MULTI_ADDR_SET:
326 case BNEP_FILTER_NET_TYPE_SET:
327 /* Pull: ctrl type (1 b), len (2 b), data (len bytes) */
328 if (!skb_pull(skb, 3 + *(u16 *)(skb->data + 1) * 2))
329 goto badframe;
330 break;
331 default:
332 kfree_skb(skb);
333 return 0;
334 }
335 } else {
336 skb_reset_mac_header(skb);
316 337
317 s->eh.h_proto = get_unaligned((__be16 *) (skb->data - 2)); 338 /* Verify and pull out header */
339 if (!skb_pull(skb, __bnep_rx_hlen[type & BNEP_TYPE_MASK]))
340 goto badframe;
341
342 s->eh.h_proto = get_unaligned((__be16 *) (skb->data - 2));
343 }
318 344
319 if (type & BNEP_EXT_HEADER) { 345 if (type & BNEP_EXT_HEADER) {
320 if (bnep_rx_extension(s, skb) < 0) 346 if (bnep_rx_extension(s, skb) < 0)