diff options
author | John W. Linville <linville@tuxdriver.com> | 2014-10-02 13:56:19 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2014-10-02 13:56:19 -0400 |
commit | f6cd071891c5c7971866fda8340202b73ce35206 (patch) | |
tree | 95dbb8769f69db80f1fbcca9ee813ce474b99a22 /net | |
parent | 574a7930d7c4d0fe4295868e52a5277bd9595b5e (diff) | |
parent | 9c238ca8ec79c38ab22762b44aeaf7a42fc97b18 (diff) |
Merge branch 'for-upstream' of git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth-next
Diffstat (limited to 'net')
-rw-r--r-- | net/bluetooth/6lowpan.c | 145 | ||||
-rw-r--r-- | net/bluetooth/l2cap_core.c | 13 |
2 files changed, 103 insertions, 55 deletions
diff --git a/net/bluetooth/6lowpan.c b/net/bluetooth/6lowpan.c index 0920cb6ed572..c2e0d14433df 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 | ||
429 | static int header_create(struct sk_buff *skb, struct net_device *netdev, | 429 | static 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,15 +474,37 @@ 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); | ||
489 | 486 | ||
490 | return lowpan_header_compress(skb, netdev, type, daddr, saddr, len); | 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 | |||
494 | static 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)); | ||
506 | |||
507 | return 0; | ||
491 | } | 508 | } |
492 | 509 | ||
493 | /* Packet to BT LE device */ | 510 | /* Packet to BT LE device */ |
@@ -529,11 +546,12 @@ static int send_pkt(struct l2cap_chan *chan, struct sk_buff *skb, | |||
529 | return err; | 546 | return err; |
530 | } | 547 | } |
531 | 548 | ||
532 | static void send_mcast_pkt(struct sk_buff *skb, struct net_device *netdev) | 549 | static int send_mcast_pkt(struct sk_buff *skb, struct net_device *netdev) |
533 | { | 550 | { |
534 | struct sk_buff *local_skb; | 551 | struct sk_buff *local_skb; |
535 | struct lowpan_dev *entry, *tmp; | 552 | struct lowpan_dev *entry, *tmp; |
536 | unsigned long flags; | 553 | unsigned long flags; |
554 | int err = 0; | ||
537 | 555 | ||
538 | read_lock_irqsave(&devices_lock, flags); | 556 | read_lock_irqsave(&devices_lock, flags); |
539 | 557 | ||
@@ -547,57 +565,77 @@ static void send_mcast_pkt(struct sk_buff *skb, struct net_device *netdev) | |||
547 | dev = lowpan_dev(entry->netdev); | 565 | dev = lowpan_dev(entry->netdev); |
548 | 566 | ||
549 | list_for_each_entry_safe(pentry, ptmp, &dev->peers, list) { | 567 | list_for_each_entry_safe(pentry, ptmp, &dev->peers, list) { |
568 | int ret; | ||
569 | |||
550 | local_skb = skb_clone(skb, GFP_ATOMIC); | 570 | local_skb = skb_clone(skb, GFP_ATOMIC); |
551 | 571 | ||
552 | send_pkt(pentry->chan, local_skb, netdev); | 572 | BT_DBG("xmit %s to %pMR type %d IP %pI6c chan %p", |
573 | netdev->name, | ||
574 | &pentry->chan->dst, pentry->chan->dst_type, | ||
575 | &pentry->peer_addr, pentry->chan); | ||
576 | ret = send_pkt(pentry->chan, local_skb, netdev); | ||
577 | if (ret < 0) | ||
578 | err = ret; | ||
553 | 579 | ||
554 | kfree_skb(local_skb); | 580 | kfree_skb(local_skb); |
555 | } | 581 | } |
556 | } | 582 | } |
557 | 583 | ||
558 | read_unlock_irqrestore(&devices_lock, flags); | 584 | read_unlock_irqrestore(&devices_lock, flags); |
585 | |||
586 | return err; | ||
559 | } | 587 | } |
560 | 588 | ||
561 | static netdev_tx_t bt_xmit(struct sk_buff *skb, struct net_device *netdev) | 589 | static netdev_tx_t bt_xmit(struct sk_buff *skb, struct net_device *netdev) |
562 | { | 590 | { |
563 | int err = 0; | 591 | int err = 0; |
564 | struct lowpan_dev *dev; | ||
565 | struct lowpan_peer *peer; | ||
566 | bdaddr_t addr; | 592 | bdaddr_t addr; |
567 | u8 addr_type; | 593 | u8 addr_type; |
594 | struct sk_buff *tmpskb; | ||
568 | 595 | ||
569 | if (ipv6_addr_is_multicast(&lowpan_cb(skb)->addr)) { | 596 | /* We must take a copy of the skb before we modify/replace the ipv6 |
570 | /* We need to send the packet to every device | 597 | * header as the header could be used elsewhere |
571 | * behind this interface. | 598 | */ |
572 | */ | 599 | tmpskb = skb_unshare(skb, GFP_ATOMIC); |
573 | send_mcast_pkt(skb, netdev); | 600 | if (!tmpskb) { |
574 | } else { | 601 | kfree_skb(skb); |
575 | unsigned long flags; | 602 | return NET_XMIT_DROP; |
576 | 603 | } | |
577 | convert_dest_bdaddr(&lowpan_cb(skb)->addr, &addr, &addr_type); | 604 | skb = tmpskb; |
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 | 605 | ||
586 | BT_DBG("xmit %s to %pMR type %d IP %pI6c peer %p", | 606 | /* Return values from setup_header() |
587 | netdev->name, &addr, addr_type, | 607 | * <0 - error, packet is dropped |
588 | &lowpan_cb(skb)->addr, peer); | 608 | * 0 - this is a multicast packet |
609 | * 1 - this is unicast packet | ||
610 | */ | ||
611 | err = setup_header(skb, netdev, &addr, &addr_type); | ||
612 | if (err < 0) { | ||
613 | kfree_skb(skb); | ||
614 | return NET_XMIT_DROP; | ||
615 | } | ||
589 | 616 | ||
590 | if (peer && peer->chan) | 617 | if (err) { |
591 | err = send_pkt(peer->chan, skb, netdev); | 618 | if (lowpan_cb(skb)->chan) { |
592 | else | 619 | BT_DBG("xmit %s to %pMR type %d IP %pI6c chan %p", |
620 | netdev->name, &addr, addr_type, | ||
621 | &lowpan_cb(skb)->addr, lowpan_cb(skb)->chan); | ||
622 | err = send_pkt(lowpan_cb(skb)->chan, skb, netdev); | ||
623 | } else { | ||
593 | err = -ENOENT; | 624 | err = -ENOENT; |
625 | } | ||
626 | } else { | ||
627 | /* We need to send the packet to every device behind this | ||
628 | * interface. | ||
629 | */ | ||
630 | err = send_mcast_pkt(skb, netdev); | ||
594 | } | 631 | } |
632 | |||
595 | dev_kfree_skb(skb); | 633 | dev_kfree_skb(skb); |
596 | 634 | ||
597 | if (err) | 635 | if (err) |
598 | BT_DBG("ERROR: xmit failed (%d)", err); | 636 | BT_DBG("ERROR: xmit failed (%d)", err); |
599 | 637 | ||
600 | return (err < 0) ? NET_XMIT_DROP : err; | 638 | return err < 0 ? NET_XMIT_DROP : err; |
601 | } | 639 | } |
602 | 640 | ||
603 | static const struct net_device_ops netdev_ops = { | 641 | static const struct net_device_ops netdev_ops = { |
@@ -617,7 +655,8 @@ static void netdev_setup(struct net_device *dev) | |||
617 | dev->needed_tailroom = 0; | 655 | dev->needed_tailroom = 0; |
618 | dev->mtu = IPV6_MIN_MTU; | 656 | dev->mtu = IPV6_MIN_MTU; |
619 | dev->tx_queue_len = 0; | 657 | dev->tx_queue_len = 0; |
620 | dev->flags = IFF_RUNNING | IFF_POINTOPOINT; | 658 | dev->flags = IFF_RUNNING | IFF_POINTOPOINT | |
659 | IFF_MULTICAST; | ||
621 | dev->watchdog_timeo = 0; | 660 | dev->watchdog_timeo = 0; |
622 | 661 | ||
623 | dev->netdev_ops = &netdev_ops; | 662 | dev->netdev_ops = &netdev_ops; |
@@ -950,6 +989,9 @@ static void chan_suspend_cb(struct l2cap_chan *chan) | |||
950 | 989 | ||
951 | BT_DBG("chan %p conn %p skb %p", chan, chan->conn, skb); | 990 | BT_DBG("chan %p conn %p skb %p", chan, chan->conn, skb); |
952 | 991 | ||
992 | if (!skb) | ||
993 | return; | ||
994 | |||
953 | lowpan_cb(skb)->status = -EAGAIN; | 995 | lowpan_cb(skb)->status = -EAGAIN; |
954 | } | 996 | } |
955 | 997 | ||
@@ -959,6 +1001,9 @@ static void chan_resume_cb(struct l2cap_chan *chan) | |||
959 | 1001 | ||
960 | BT_DBG("chan %p conn %p skb %p", chan, chan->conn, skb); | 1002 | BT_DBG("chan %p conn %p skb %p", chan, chan->conn, skb); |
961 | 1003 | ||
1004 | if (!skb) | ||
1005 | return; | ||
1006 | |||
962 | lowpan_cb(skb)->status = 0; | 1007 | lowpan_cb(skb)->status = 0; |
963 | } | 1008 | } |
964 | 1009 | ||
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index 8d53fc57faba..b6f9777e057d 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c | |||
@@ -6980,8 +6980,6 @@ int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid, | |||
6980 | 6980 | ||
6981 | hci_dev_lock(hdev); | 6981 | hci_dev_lock(hdev); |
6982 | 6982 | ||
6983 | l2cap_chan_lock(chan); | ||
6984 | |||
6985 | if (!is_valid_psm(__le16_to_cpu(psm), dst_type) && !cid && | 6983 | if (!is_valid_psm(__le16_to_cpu(psm), dst_type) && !cid && |
6986 | chan->chan_type != L2CAP_CHAN_RAW) { | 6984 | chan->chan_type != L2CAP_CHAN_RAW) { |
6987 | err = -EINVAL; | 6985 | err = -EINVAL; |
@@ -7078,17 +7076,20 @@ int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid, | |||
7078 | goto done; | 7076 | goto done; |
7079 | } | 7077 | } |
7080 | 7078 | ||
7079 | mutex_lock(&conn->chan_lock); | ||
7080 | l2cap_chan_lock(chan); | ||
7081 | |||
7081 | if (cid && __l2cap_get_chan_by_dcid(conn, cid)) { | 7082 | if (cid && __l2cap_get_chan_by_dcid(conn, cid)) { |
7082 | hci_conn_drop(hcon); | 7083 | hci_conn_drop(hcon); |
7083 | err = -EBUSY; | 7084 | err = -EBUSY; |
7084 | goto done; | 7085 | goto chan_unlock; |
7085 | } | 7086 | } |
7086 | 7087 | ||
7087 | /* Update source addr of the socket */ | 7088 | /* Update source addr of the socket */ |
7088 | bacpy(&chan->src, &hcon->src); | 7089 | bacpy(&chan->src, &hcon->src); |
7089 | chan->src_type = bdaddr_type(hcon, hcon->src_type); | 7090 | chan->src_type = bdaddr_type(hcon, hcon->src_type); |
7090 | 7091 | ||
7091 | l2cap_chan_add(conn, chan); | 7092 | __l2cap_chan_add(conn, chan); |
7092 | 7093 | ||
7093 | /* l2cap_chan_add takes its own ref so we can drop this one */ | 7094 | /* l2cap_chan_add takes its own ref so we can drop this one */ |
7094 | hci_conn_drop(hcon); | 7095 | hci_conn_drop(hcon); |
@@ -7114,8 +7115,10 @@ int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid, | |||
7114 | 7115 | ||
7115 | err = 0; | 7116 | err = 0; |
7116 | 7117 | ||
7117 | done: | 7118 | chan_unlock: |
7118 | l2cap_chan_unlock(chan); | 7119 | l2cap_chan_unlock(chan); |
7120 | mutex_unlock(&conn->chan_lock); | ||
7121 | done: | ||
7119 | hci_dev_unlock(hdev); | 7122 | hci_dev_unlock(hdev); |
7120 | hci_dev_put(hdev); | 7123 | hci_dev_put(hdev); |
7121 | return err; | 7124 | return err; |