[PATCH 0/2] Bluetooth: dial the peer's on-air address when we cannot resolve
From: Radek Podgorny
Date: Mon Sep 07 2026 - 19:25:01 EST
On a controller that cannot resolve private addresses, an outgoing LE
connection to a peer that is advertising an RPA goes out on the peer's
identity address and cannot succeed. It burns a full create-connection
timeout, and because such a controller also has no extended scanning it
cannot scan while it is initiating, so the adapter goes deaf to every other
device for the duration.
Patch 2 picks the address to put on air instead of assuming conn->dst.
Patch 1 is its prerequisite: choosing a cached RPA is only safe while that
RPA is still current, and nothing recorded when one was last seen.
Measured on a Raspberry Pi with two controllers, a CYW43438 as the central
and a Realtek dongle as the peer, Arch Linux ARM 7.2, BlueZ 5.87. The peer
advertises an RPA generated from a fixed IRK that is also loaded into the
central, so advertisements resolve and the conditions the patches care about
hold. Numbers are in patch 2.
Neither of those adapters reports LL Privacy, so the branch that defers to a
controller's resolving list was measured separately, on an Intel controller
that does. With the peer programmed into that controller's resolving list the
host puts the identity address into LE Extended Create Connection, and the
controller resolves it and connects:
LE Enhanced Connection Complete (0x0a)
Status: Success (0x00)
Peer address type: Resolved Public (0x02)
Peer address: 3C:78:95:78:37:C3
Peer resolvable private address: 6D:CA:DB:24:14:E9 (Resolvable)
Before the peer is in the resolving list, the same setup dials the peer's RPA
instead. So both directions of that branch are covered: the host defers when
the controller can translate, and substitutes when it cannot.
What this series does not establish:
- Patch 1 has no independent observable. It ships as patch 2's
prerequisite and its effect is only visible through patch 2's behaviour.
- Three controllers, one peer, two kernel versions. The fallback branches
were exercised on a CYW43438, the resolving-list branch on one Intel
controller. The peer is a Linux host running BlueZ rather than an
embedded peripheral, so nothing here speaks to other stacks.
Two further patches were carried in earlier revisions of this work and
dropped after each was built and measured on its own; neither turned out to
have a reachable effect. An earlier form of one of them also corrupted
Secure Connections pairing. They are not in this series.
Tooling: written with Claude (claude-opus-5) assisting, per
Documentation/process/coding-assistants.rst, hence the Assisted-by tags.
The session covered reading the existing address handling, drafting the
patches, and analysing the btmon captures. Every hypothesis that could be
tested on hardware was tested there, and the ones that failed were dropped
rather than argued. All patches are checkpatch --strict clean and build
without new warnings.
Radek Podgorny (2):
Bluetooth: record when an IRK's RPA was last seen
Bluetooth: put the peer's on-air address on air when we cannot resolve
include/net/bluetooth/hci_core.h | 4 ++
net/bluetooth/hci_core.c | 4 ++
net/bluetooth/hci_sync.c | 82 +++++++++++++++++++++++++++++---
3 files changed, 83 insertions(+), 7 deletions(-)
base-commit: 755cf7adf8dd2d12627cb7de223d35b12228e2f5
--
2.55.0