aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
Diffstat (limited to 'net')
-rw-r--r--net/bluetooth/6lowpan.c135
1 files changed, 83 insertions, 52 deletions
diff --git a/net/bluetooth/6lowpan.c b/net/bluetooth/6lowpan.c
index 5d3e6202da3d..2ec7c84c2000 100644
--- a/net/bluetooth/6lowpan.c
+++ b/net/bluetooth/6lowpan.c
@@ -426,38 +426,33 @@ static void convert_dest_bdaddr(struct in6_addr *ip6_daddr,
426 *addr_type = get_addr_type_from_eui64(addr->b[5]); 426 *addr_type = get_addr_type_from_eui64(addr->b[5]);
427} 427}
428 428
429static int header_create(struct sk_buff *skb, struct net_device *netdev, 429static int setup_header(struct sk_buff *skb, struct net_device *netdev,
430 unsigned short type, const void *_daddr, 430 bdaddr_t *peer_addr, u8 *peer_addr_type)
431 const void *_saddr, unsigned int len)
432{ 431{
433 struct ipv6hdr *hdr; 432 struct in6_addr ipv6_daddr;
434 struct lowpan_dev *dev; 433 struct lowpan_dev *dev;
435 struct lowpan_peer *peer; 434 struct lowpan_peer *peer;
436 bdaddr_t addr, *any = BDADDR_ANY; 435 bdaddr_t addr, *any = BDADDR_ANY;
437 u8 *saddr, *daddr = any->b; 436 u8 *daddr = any->b;
438 u8 addr_type; 437 int err, status = 0;
439
440 if (type != ETH_P_IPV6)
441 return -EINVAL;
442
443 hdr = ipv6_hdr(skb);
444 438
445 dev = lowpan_dev(netdev); 439 dev = lowpan_dev(netdev);
446 440
447 if (ipv6_addr_is_multicast(&hdr->daddr)) { 441 memcpy(&ipv6_daddr, &lowpan_cb(skb)->addr, sizeof(ipv6_daddr));
448 memcpy(&lowpan_cb(skb)->addr, &hdr->daddr, 442
449 sizeof(struct in6_addr)); 443 if (ipv6_addr_is_multicast(&ipv6_daddr)) {
450 lowpan_cb(skb)->chan = NULL; 444 lowpan_cb(skb)->chan = NULL;
451 } else { 445 } else {
452 unsigned long flags; 446 unsigned long flags;
447 u8 addr_type;
453 448
454 /* Get destination BT device from skb. 449 /* Get destination BT device from skb.
455 * If there is no such peer then discard the packet. 450 * If there is no such peer then discard the packet.
456 */ 451 */
457 convert_dest_bdaddr(&hdr->daddr, &addr, &addr_type); 452 convert_dest_bdaddr(&ipv6_daddr, &addr, &addr_type);
458 453
459 BT_DBG("dest addr %pMR type %d IP %pI6c", &addr, 454 BT_DBG("dest addr %pMR type %d IP %pI6c", &addr,
460 addr_type, &hdr->daddr); 455 addr_type, &ipv6_daddr);
461 456
462 read_lock_irqsave(&devices_lock, flags); 457 read_lock_irqsave(&devices_lock, flags);
463 peer = peer_lookup_ba(dev, &addr, addr_type); 458 peer = peer_lookup_ba(dev, &addr, addr_type);
@@ -470,7 +465,7 @@ static int header_create(struct sk_buff *skb, struct net_device *netdev,
470 * the destination address. 465 * the destination address.
471 */ 466 */
472 read_lock_irqsave(&devices_lock, flags); 467 read_lock_irqsave(&devices_lock, flags);
473 peer = peer_lookup_dst(dev, &hdr->daddr, skb); 468 peer = peer_lookup_dst(dev, &ipv6_daddr, skb);
474 read_unlock_irqrestore(&devices_lock, flags); 469 read_unlock_irqrestore(&devices_lock, flags);
475 if (!peer) { 470 if (!peer) {
476 BT_DBG("no such peer %pMR found", &addr); 471 BT_DBG("no such peer %pMR found", &addr);
@@ -479,29 +474,56 @@ static int header_create(struct sk_buff *skb, struct net_device *netdev,
479 } 474 }
480 475
481 daddr = peer->eui64_addr; 476 daddr = peer->eui64_addr;
482 477 *peer_addr = addr;
483 memcpy(&lowpan_cb(skb)->addr, &hdr->daddr, 478 *peer_addr_type = addr_type;
484 sizeof(struct in6_addr));
485 lowpan_cb(skb)->chan = peer->chan; 479 lowpan_cb(skb)->chan = peer->chan;
480
481 status = 1;
486 } 482 }
487 483
488 saddr = dev->netdev->dev_addr; 484 lowpan_header_compress(skb, netdev, ETH_P_IPV6, daddr,
485 dev->netdev->dev_addr, skb->len);
486
487 err = dev_hard_header(skb, netdev, ETH_P_IPV6, NULL, NULL, 0);
488 if (err < 0)
489 return err;
490
491 return status;
492}
493
494static int header_create(struct sk_buff *skb, struct net_device *netdev,
495 unsigned short type, const void *_daddr,
496 const void *_saddr, unsigned int len)
497{
498 struct ipv6hdr *hdr;
499
500 if (type != ETH_P_IPV6)
501 return -EINVAL;
502
503 hdr = ipv6_hdr(skb);
504
505 memcpy(&lowpan_cb(skb)->addr, &hdr->daddr, sizeof(struct in6_addr));
489 506
490 return lowpan_header_compress(skb, netdev, type, daddr, saddr, len); 507 return 0;
491} 508}
492 509
493/* Packet to BT LE device */ 510/* Packet to BT LE device */
494static int send_pkt(struct l2cap_chan *chan, struct sk_buff *skb, 511static int send_pkt(struct l2cap_chan *chan, struct sk_buff *skb,
495 struct net_device *netdev) 512 struct net_device *netdev, bool is_mcast)
496{ 513{
497 struct msghdr msg; 514 struct msghdr msg;
498 struct kvec iv; 515 struct kvec iv;
499 int err; 516 int err;
500 517
501 /* Remember the skb so that we can send EAGAIN to the caller if 518 /* Remember the skb so that we can send EAGAIN to the caller if
502 * we run out of credits. 519 * we run out of credits. This is not done for multicast packets
520 * because we generate mcast packet in this module and are not
521 * really able to remember the skb after this packet is sent.
503 */ 522 */
504 chan->data = skb; 523 if (is_mcast)
524 chan->data = NULL;
525 else
526 chan->data = skb;
505 527
506 memset(&msg, 0, sizeof(msg)); 528 memset(&msg, 0, sizeof(msg));
507 msg.msg_iov = (struct iovec *) &iv; 529 msg.msg_iov = (struct iovec *) &iv;
@@ -549,7 +571,11 @@ static void send_mcast_pkt(struct sk_buff *skb, struct net_device *netdev)
549 list_for_each_entry_safe(pentry, ptmp, &dev->peers, list) { 571 list_for_each_entry_safe(pentry, ptmp, &dev->peers, list) {
550 local_skb = skb_clone(skb, GFP_ATOMIC); 572 local_skb = skb_clone(skb, GFP_ATOMIC);
551 573
552 send_pkt(pentry->chan, local_skb, netdev); 574 BT_DBG("xmit %s to %pMR type %d IP %pI6c chan %p",
575 netdev->name,
576 &pentry->chan->dst, pentry->chan->dst_type,
577 &pentry->peer_addr, pentry->chan);
578 send_pkt(pentry->chan, local_skb, netdev, true);
553 579
554 kfree_skb(local_skb); 580 kfree_skb(local_skb);
555 } 581 }
@@ -561,43 +587,48 @@ static void send_mcast_pkt(struct sk_buff *skb, struct net_device *netdev)
561static netdev_tx_t bt_xmit(struct sk_buff *skb, struct net_device *netdev) 587static netdev_tx_t bt_xmit(struct sk_buff *skb, struct net_device *netdev)
562{ 588{
563 int err = 0; 589 int err = 0;
564 struct lowpan_dev *dev;
565 struct lowpan_peer *peer;
566 bdaddr_t addr; 590 bdaddr_t addr;
567 u8 addr_type; 591 u8 addr_type;
568 592
569 if (ipv6_addr_is_multicast(&lowpan_cb(skb)->addr)) { 593 /* We must take a copy of the skb before we modify/replace the ipv6
570 /* We need to send the packet to every device 594 * header as the header could be used elsewhere
571 * behind this interface. 595 */
572 */ 596 skb = skb_unshare(skb, GFP_ATOMIC);
573 send_mcast_pkt(skb, netdev); 597 if (!skb)
574 } else { 598 return NET_XMIT_DROP;
575 unsigned long flags;
576
577 convert_dest_bdaddr(&lowpan_cb(skb)->addr, &addr, &addr_type);
578 dev = lowpan_dev(netdev);
579
580 read_lock_irqsave(&devices_lock, flags);
581 peer = peer_lookup_ba(dev, &addr, addr_type);
582 if (!peer)
583 peer = peer_lookup_dst(dev, &lowpan_cb(skb)->addr, skb);
584 read_unlock_irqrestore(&devices_lock, flags);
585 599
586 BT_DBG("xmit %s to %pMR type %d IP %pI6c peer %p", 600 /* Return values from setup_header()
587 netdev->name, &addr, addr_type, 601 * <0 - error, packet is dropped
588 &lowpan_cb(skb)->addr, peer); 602 * 0 - this is a multicast packet
603 * 1 - this is unicast packet
604 */
605 err = setup_header(skb, netdev, &addr, &addr_type);
606 if (err < 0) {
607 kfree_skb(skb);
608 return NET_XMIT_DROP;
609 }
589 610
590 if (peer && peer->chan) 611 if (err) {
591 err = send_pkt(peer->chan, skb, netdev); 612 if (lowpan_cb(skb)->chan) {
592 else 613 BT_DBG("xmit %s to %pMR type %d IP %pI6c chan %p",
614 netdev->name, &addr, addr_type,
615 &lowpan_cb(skb)->addr, lowpan_cb(skb)->chan);
616 err = send_pkt(lowpan_cb(skb)->chan, skb, netdev,
617 false);
618 } else {
593 err = -ENOENT; 619 err = -ENOENT;
620 }
621 } else {
622 /* We need to send the packet to every device behind this
623 * interface.
624 */
625 send_mcast_pkt(skb, netdev);
594 } 626 }
595 dev_kfree_skb(skb);
596 627
597 if (err) 628 if (err)
598 BT_DBG("ERROR: xmit failed (%d)", err); 629 BT_DBG("ERROR: xmit failed (%d)", err);
599 630
600 return (err < 0) ? NET_XMIT_DROP : err; 631 return err < 0 ? NET_XMIT_DROP : err;
601} 632}
602 633
603static const struct net_device_ops netdev_ops = { 634static const struct net_device_ops netdev_ops = {