summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJosua Mayer <josua.mayer@jm0.eu>2019-07-06 17:54:47 +0200
committerMarcel Holtmann <marcel@holtmann.org>2019-07-06 21:33:55 +0200
commit5636376c26502c39260853e529e9467f79f95931 (patch)
tree3d2c1a58b55197596b8580fec3466015abb777b2
parentBluetooth: 6lowpan: search for destination address in all peers (diff)
downloadlinux-5636376c26502c39260853e529e9467f79f95931.tar.xz
linux-5636376c26502c39260853e529e9467f79f95931.zip
Bluetooth: 6lowpan: check neighbour table for SLAAC
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>
-rw-r--r--net/bluetooth/6lowpan.c15
1 files changed, 15 insertions, 0 deletions
diff --git a/net/bluetooth/6lowpan.c b/net/bluetooth/6lowpan.c
index 9001bf331d56..f4e548e7b985 100644
--- a/net/bluetooth/6lowpan.c
+++ b/net/bluetooth/6lowpan.c
@@ -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;