diff options
author | Alexander Aring <alex.aring@gmail.com> | 2015-10-13 07:42:55 -0400 |
---|---|---|
committer | Marcel Holtmann <marcel@holtmann.org> | 2015-10-20 18:49:24 -0400 |
commit | cefdb801c80736017b5a0d97a4a9f816d5a98fc4 (patch) | |
tree | b24038cd412000fafe0e31dcb01a0166572c641f /net | |
parent | 71cd2aa53dbf9eb8cb954fc9e65de8dab774b7f6 (diff) |
bluetooth: 6lowpan: use lowpan dispatch helpers
This patch adds a check if the dataroom of skb contains a dispatch value
by checking if skb->len != 0. This patch also change the dispatch
evaluation by the recently introduced helpers for checking the common
6LoWPAN dispatch values for IPv6 and IPHC header.
There was also a forgotten else branch which should drop the packet if
no matching dispatch is available.
Signed-off-by: Alexander Aring <alex.aring@gmail.com>
Acked-by: Jukka Rissanen <jukka.rissanen@linux.intel.com>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
Diffstat (limited to 'net')
-rw-r--r-- | net/bluetooth/6lowpan.c | 57 |
1 files changed, 27 insertions, 30 deletions
diff --git a/net/bluetooth/6lowpan.c b/net/bluetooth/6lowpan.c index db73b8a1433f..665bf38bd03b 100644 --- a/net/bluetooth/6lowpan.c +++ b/net/bluetooth/6lowpan.c | |||
@@ -314,15 +314,17 @@ static int recv_pkt(struct sk_buff *skb, struct net_device *dev, | |||
314 | if (!netif_running(dev)) | 314 | if (!netif_running(dev)) |
315 | goto drop; | 315 | goto drop; |
316 | 316 | ||
317 | if (dev->type != ARPHRD_6LOWPAN) | 317 | if (dev->type != ARPHRD_6LOWPAN || !skb->len) |
318 | goto drop; | 318 | goto drop; |
319 | 319 | ||
320 | skb_reset_network_header(skb); | ||
321 | |||
320 | skb = skb_share_check(skb, GFP_ATOMIC); | 322 | skb = skb_share_check(skb, GFP_ATOMIC); |
321 | if (!skb) | 323 | if (!skb) |
322 | goto drop; | 324 | goto drop; |
323 | 325 | ||
324 | /* check that it's our buffer */ | 326 | /* check that it's our buffer */ |
325 | if (skb->data[0] == LOWPAN_DISPATCH_IPV6) { | 327 | if (lowpan_is_ipv6(*skb_network_header(skb))) { |
326 | /* Copy the packet so that the IPv6 header is | 328 | /* Copy the packet so that the IPv6 header is |
327 | * properly aligned. | 329 | * properly aligned. |
328 | */ | 330 | */ |
@@ -334,7 +336,6 @@ static int recv_pkt(struct sk_buff *skb, struct net_device *dev, | |||
334 | local_skb->protocol = htons(ETH_P_IPV6); | 336 | local_skb->protocol = htons(ETH_P_IPV6); |
335 | local_skb->pkt_type = PACKET_HOST; | 337 | local_skb->pkt_type = PACKET_HOST; |
336 | 338 | ||
337 | skb_reset_network_header(local_skb); | ||
338 | skb_set_transport_header(local_skb, sizeof(struct ipv6hdr)); | 339 | skb_set_transport_header(local_skb, sizeof(struct ipv6hdr)); |
339 | 340 | ||
340 | if (give_skb_to_upper(local_skb, dev) != NET_RX_SUCCESS) { | 341 | if (give_skb_to_upper(local_skb, dev) != NET_RX_SUCCESS) { |
@@ -347,38 +348,34 @@ static int recv_pkt(struct sk_buff *skb, struct net_device *dev, | |||
347 | 348 | ||
348 | consume_skb(local_skb); | 349 | consume_skb(local_skb); |
349 | consume_skb(skb); | 350 | consume_skb(skb); |
350 | } else { | 351 | } else if (lowpan_is_iphc(*skb_network_header(skb))) { |
351 | switch (skb->data[0] & 0xe0) { | 352 | local_skb = skb_clone(skb, GFP_ATOMIC); |
352 | case LOWPAN_DISPATCH_IPHC: /* ipv6 datagram */ | 353 | if (!local_skb) |
353 | local_skb = skb_clone(skb, GFP_ATOMIC); | 354 | goto drop; |
354 | if (!local_skb) | ||
355 | goto drop; | ||
356 | 355 | ||
357 | ret = iphc_decompress(local_skb, dev, chan); | 356 | ret = iphc_decompress(local_skb, dev, chan); |
358 | if (ret < 0) { | 357 | if (ret < 0) { |
359 | kfree_skb(local_skb); | 358 | kfree_skb(local_skb); |
360 | goto drop; | 359 | goto drop; |
361 | } | 360 | } |
362 | 361 | ||
363 | local_skb->protocol = htons(ETH_P_IPV6); | 362 | local_skb->protocol = htons(ETH_P_IPV6); |
364 | local_skb->pkt_type = PACKET_HOST; | 363 | local_skb->pkt_type = PACKET_HOST; |
365 | local_skb->dev = dev; | 364 | local_skb->dev = dev; |
366 | 365 | ||
367 | if (give_skb_to_upper(local_skb, dev) | 366 | if (give_skb_to_upper(local_skb, dev) |
368 | != NET_RX_SUCCESS) { | 367 | != NET_RX_SUCCESS) { |
369 | kfree_skb(local_skb); | 368 | kfree_skb(local_skb); |
370 | goto drop; | 369 | goto drop; |
371 | } | 370 | } |
372 | 371 | ||
373 | dev->stats.rx_bytes += skb->len; | 372 | dev->stats.rx_bytes += skb->len; |
374 | dev->stats.rx_packets++; | 373 | dev->stats.rx_packets++; |
375 | 374 | ||
376 | consume_skb(local_skb); | 375 | consume_skb(local_skb); |
377 | consume_skb(skb); | 376 | consume_skb(skb); |
378 | break; | 377 | } else { |
379 | default: | 378 | goto drop; |
380 | break; | ||
381 | } | ||
382 | } | 379 | } |
383 | 380 | ||
384 | return NET_RX_SUCCESS; | 381 | return NET_RX_SUCCESS; |