]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
Bluetooth: 6lowpan: check neighbour table for SLAAC
authorJosua Mayer <josua.mayer@jm0.eu>
Sat, 6 Jul 2019 15:54:47 +0000 (17:54 +0200)
committerMarcel Holtmann <marcel@holtmann.org>
Sat, 6 Jul 2019 19:33:55 +0000 (21:33 +0200)
Like any IPv6 capable device, 6LNs can have multiple addresses assigned
using SLAAC and made known through neighbour advertisements.
After checking the destination address against all peers link-local
addresses, consult the neighbour cache for additional known addresses.

RFC7668 defines the scope of Neighbor Advertisements in Section 3.2.3:
1. "A Bluetooth LE 6LN MUST NOT register its link-local address"
2. "A Bluetooth LE 6LN MUST register its non-link-local addresses with
the 6LBR by sending Neighbor Solicitation (NS) messages ..."

Due to these constranits both the link-local addresses tracked in the
list of 6lowpan peers, and the neighbour cache have to be used when
identifying the 6lowpan peer for a destination address.

Acked-by: Jukka Rissanen <jukka.rissanen@linux.intel.com>
Tested-by: Michael Scott <mike@foundries.io>
Signed-off-by: Josua Mayer <josua.mayer@jm0.eu>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
net/bluetooth/6lowpan.c

index 9001bf331d56d366d51e0756cd388801a347d4d9..f4e548e7b985365e2946a6f39829e8d8e5f83f3f 100644 (file)
@@ -164,6 +164,7 @@ static inline struct lowpan_peer *peer_lookup_dst(struct lowpan_btle_dev *dev,
        int count = atomic_read(&dev->peer_count);
        const struct in6_addr *nexthop;
        struct lowpan_peer *peer;
+       struct neighbour *neigh;
 
        BT_DBG("peers %d addr %pI6c rt %p", count, daddr, rt);
 
@@ -215,6 +216,20 @@ static inline struct lowpan_peer *peer_lookup_dst(struct lowpan_btle_dev *dev,
                }
        }
 
+       /* use the neighbour cache for matching addresses assigned by SLAAC
+       */
+       neigh = __ipv6_neigh_lookup(dev->netdev, nexthop);
+       if (neigh) {
+               list_for_each_entry_rcu(peer, &dev->peers, list) {
+                       if (!memcmp(neigh->ha, peer->lladdr, ETH_ALEN)) {
+                               neigh_release(neigh);
+                               rcu_read_unlock();
+                               return peer;
+                       }
+               }
+               neigh_release(neigh);
+       }
+
        rcu_read_unlock();
 
        return NULL;