What are BLE filter policies – bluez tutorial

 

Scanner Filter 4.2, Initiator Filter & Real Sniffer Captures
Chapter 8 Sections 8.15.2–8.17 — Extended RPA Filter Policies, Initiator Filter, Proximity Profile Air Log & Chapter Summary
Scanner Modes
2 (4.0) + 2 (4.2)
Initiator Modes
2 total
Sniffer Frames
676 to 4785
Link Layer
5 states, complete
Keywords:

BLE scanner filter 4.2 RPA BLE initiator filter policy BLE sniffer proximity profile BLE LL_VERSION_IND frames 676 677 BLE encryption start frames 702-708 BLE channel map update sniffer BLE LL_TERMINATE_IND frame 4785 BLE chapter 8 summary

Continuing Section 8.15.2 — Scanner Filter

The previous file (PDF 46) introduced the Scanner Filter Policy and its BLE 4.0 modes. This file picks up with the BLE 4.2 extended scanner filter policies that handle Resolvable Private Addresses, then covers the Initiator Filter Policy, a real sniffer capture showing all the LLCP procedures working together, and closes with the full Chapter 8 summary.

8.15.2 — Scanner Filter Policy — BLE 4.2 Extended Modes

The Problem BLE 4.2 Extended Modes Solve

In BLE 4.0, when a scanner received an ADV_DIRECT_IND (Connectable Directed advertising), it checked whether the InitA field — the address the Advertiser was trying to reach — matched its own address. If not, it discarded the packet. Simple and efficient.

But this breaks when both devices use Resolvable Private Addresses (RPAs). Here is why: the Advertiser puts the scanner’s last known RPA in the InitA field. But RPAs rotate every 15 minutes. If the Advertiser is using a stale RPA that was valid 20 minutes ago, the scanner’s own current address no longer matches, so the scanner discards the packet — even though the packet was genuinely meant for it.

BLE 4.2 fixed this by adding two extended scanner filter modes. In these modes, the scanner does not immediately discard an ADV_DIRECT_IND whose InitA does not match. Instead it first tries to resolve the InitA using its IRK. If the resolution succeeds — meaning the InitA was indeed a private address generated for this scanner — the packet is accepted.

BLE 4.0 vs 4.2 — Scanner Handling of ADV_DIRECT_IND with RPA
BLE 4.0 — Breaks with RPA
Receives ADV_DIRECT_IND
InitA = old RPA (e.g. 7D:A3:F1…)
Compares InitA to own current address
❌ No match → DISCARD
(even though packet was for this device)
BLE 4.2 — Handles RPA correctly
Receives ADV_DIRECT_IND
InitA = old RPA (e.g. 7D:A3:F1…)
Tries to resolve InitA using own IRK
✅ Resolution succeeds → ACCEPT
(correctly identifies intended recipient)

The two new BLE 4.2 scanner filter modes are:

Mode 2 (4.2) — White List + do not ignore directed RPA

Same as the BLE 4.0 Mode 1 (white list in use), but additionally: if a connectable directed advertising packet arrives with an InitA that is a resolvable private address, do not automatically discard it — resolve it first. The white list still applies for all other packet types.

Mode 3 (4.2) — All packets + do not ignore directed RPA

Same as the BLE 4.0 Mode 0 (all packets accepted), but additionally: if a connectable directed packet arrives with a resolvable private address in InitA, try to resolve it before deciding. The default after controller reset remains all packets accepted (same as 4.0).

The overall effect of these two extended modes is that both the Advertiser and the Scanner can now freely use Resolvable Private Addresses without their directed advertising breaking. The filter policy resolves the InitA before making the accept/discard decision — strengthening Link Layer Privacy for directed advertising as well as undirected.

/* Setting BLE 4.2 extended scanner filter policy in BlueZ */
/* Own address type must be RPA (0x02) for this to work    */

le_set_scan_parameters_cp sp;
memset(&sp, 0, sizeof(sp));
sp.type             = 0x01;           /* active scan         */
sp.interval         = htobs(0x0010);
sp.window           = htobs(0x0010);
sp.own_bdaddr_type  = 0x02;           /* 0x02 = RPA          */

/* filter values:
 * 0x00 = all packets, no WL (BLE 4.0 default)
 * 0x01 = white list only (BLE 4.0)
 * 0x02 = white list + resolve directed RPA (BLE 4.2)
 * 0x03 = all packets + resolve directed RPA (BLE 4.2)  */
sp.filter = 0x03;  /* all packets + RPA resolution */

hci_send_cmd(sock, OGF_LE_CTL,
             OCF_LE_SET_SCAN_PARAMETERS,
             LE_SET_SCAN_PARAMETERS_CP_SIZE, &sp);

8.15.3 — Initiator Filter Policy

Two Modes — White List or a Single Named Device

The Initiator Filter Policy controls which advertising packets the Initiator’s link layer acts upon when deciding to send a CONNECT_REQ. Unlike the Advertising and Scanner filter policies which use HCI parameter commands, the Initiator filter policy is specified at the moment a connection is created — inside the HCI_LE_Create_Connection command itself.

There are exactly two modes:

Mode 0 — Default

Specific Single Device (White List not in use)

The host specifies the exact address of the one device it wants to connect to inside the HCI_LE_Create_Connection command. The Initiator ignores all other advertising packets and only sends a CONNECT_REQ when it hears from that specific device.

Use when: connecting to a specific known device by address
Mode 1

Connect to Any Device in the White List

The Initiator will accept a connectable advertising packet from any device whose address is in the White List. The controller sends a CONNECT_REQ to whichever white-listed device becomes available first and reports back which address was connected to via the Peer_Address field of LE_Connection_Complete.

Use when: you have multiple equivalent sensors and want to connect to whichever is closest/available
Initiator Filter Policy Mode 1 — “Connect to Whoever Appears First”
White List contains: Sensor A, Sensor B, Sensor C
Sensor A
ADV_IND (not in range yet, Initiator ignores)
Sensor B
ADV_IND ← in white list, in range!
Initiator
CONNECT_REQ sent to Sensor B immediately
LE_Connection_Complete → Peer_Address = Sensor B’s address
/* Creating a BLE connection using BlueZ HCI                      */
/* HCI_LE_Create_Connection: OGF=0x08, OCF=0x000D                */

typedef struct {
    uint16_t scan_interval;       /* 0x0004–0x4000, units 0.625ms */
    uint16_t scan_window;         /* must be ≤ scan_interval      */
    uint8_t  filter_policy;       /* 0=specific device, 1=WL      */
    uint8_t  peer_bdaddr_type;    /* 0=public, 1=random           */
    uint8_t  peer_bdaddr[6];      /* target address (mode 0 only) */
    uint8_t  own_bdaddr_type;     /* 0=public, 2=RPA              */
    uint16_t conn_interval_min;   /* 0x0006–0x0C80 × 1.25ms      */
    uint16_t conn_interval_max;
    uint16_t conn_latency;        /* 0x0000–0x01F3                */
    uint16_t supervision_timeout; /* 0x000A–0x0C80 × 10ms        */
    uint16_t min_ce_length;       /* connection event length      */
    uint16_t max_ce_length;
} __attribute__((packed)) le_create_connection_cp;

/* Using bluetoothctl (easier for scripting):                     */
/* [bluetooth]# scan on                                           */
/* [NEW] Device AA:BB:CC:11:22:33 MySensor                        */
/* [bluetooth]# connect AA:BB:CC:11:22:33                         */

8.16 — Practical Examples — Reading a Real Air Log

Proximity Profile — What Happens After Two Devices Connect

The textbook shows a real BLE air log capture (Figure 8.33) of two devices running the Proximity profile. The Proximity profile is used for applications like “alert when the paired device moves out of range” — think a key finder or a child tracking bracelet. What makes this capture interesting is that it shows every LLCP procedure we have studied happening in sequence on a real connection.

The capture starts after the connection is already established. These are all link layer control operations, not application data. Here is what each group of frames does:

Figure 8.33 — Annotated Air Log Capture (Proximity Profile)

Frame(s)
PDU / Side
What is happening

#676 & #677
LL_VERSION_IND
M↔S
Version Exchange. Master sends its LL_VERSION_IND (#676) with its Company ID, Link Layer version, and Sub-Version. Slave immediately responds with its own (#677). Both sides now know each other’s Bluetooth spec version.

#702 to #708
Encryption
Start PDUs
Encryption Start Procedure. Six frames to enable AES-128 on the link: LL_ENC_REQ → LL_ENC_RSP → (host gets LTK) → LL_START_ENC_REQ → LL_START_ENC_RSP → LL_START_ENC_RSP. After frame #708 all data on this connection is encrypted.

#2628
#2985
#3578
LL_CHANNEL_MAP
_REQ
Master→Slave
Channel Map Updates. The Master sends three separate channel map updates over the lifetime of the connection. Each one informs the Slave of which data channels are currently usable. The radio environment changed three times — some channels developed interference and were marked as unavailable in the updated bitmap.

#4785
LL_TERMINATE_IND
Slave→Master
Termination. The Slave requests that the link be closed, including an error code indicating why. The Master acknowledges at the link layer level and both devices exit the Connection state. The host application on both sides is notified of the disconnection.

This single capture demonstrates the typical life of a real BLE connection in sequence: identify each other (Version Exchange) → secure the link (Encryption) → adapt to the radio environment (Channel Map Updates) → close cleanly (Termination). Most real BLE connections follow a very similar pattern.

/* Capturing this kind of air log with btmon in BlueZ      */
/* btmon logs all HCI traffic between host and controller  */

/* Run: sudo btmon -w proximity_capture.snoop             */
/* Then connect to the device and capture the session     */
/* Press Ctrl+C when done                                 */

/* To read the capture back:                              */
/* sudo btmon -r proximity_capture.snoop                  */

/* You will see lines like:                               */
/* @ OPEN: proximity_capture.snoop                        */
/* < HCI Command: LE Create Connection (...)              */
/* > HCI Event: LE Meta Event → Connection Complete        */
/* < HCI Command: Read Remote Version Information (...)   */
/* > HCI Event: Read Remote Version Complete              */
/*     Version: 6 (BT 4.0), Manufacturer: 0x000A (CSR)   */
/* < HCI Command: LE Start Encryption (...)               */
/* > HCI Event: Encryption Change (encrypt=1)             */
/* < HCI Command: LE Connection Update (new params)        */
/* > HCI Event: LE Connection Update Complete              */
/* < HCI Command: Disconnect (reason=0x13)                */
/* > HCI Event: Disconnection Complete                    */

Figure 8.34 — Format of Various Device Address Types

BLE supports several types of Bluetooth device addresses. Each has a different structure and purpose. Figure 8.34 from the textbook shows the format of each type. Understanding these is important for reading sniffer captures and for correctly setting address type parameters in HCI commands.

BLE Device Address Types — Format and Use

Public Address — 48 bits (6 bytes), permanent
Company ID (OUI)
24 bits — Assigned by IEEE
Identifies the manufacturer
Company Assigned
24 bits — Unique per device
Set by the manufacturer
Bits [47:46] = 00. Assigned by the Bluetooth SIG via the IEEE. This is the MAC address burned into the Bluetooth chip. Cannot be changed.

Random Static Address — 48 bits, changes only on power cycle
11
2 MSBs
Random 46 bits
Generated on first power-up, stored in flash, stays the same until next full erase
Bits [47:46] = 11. Used by devices that do not have a public address but want a stable identity that persists across reboots.

Non-Resolvable Private Address — 48 bits, changes frequently, not linked to IRK
00
2 MSBs
Random 46 bits
Purely random, not derived from any key — cannot be resolved by anyone
Bits [47:46] = 00. Nobody can trace this back to a real identity — not even a bonded device. Provides the strongest anonymity but makes it impossible for bonded devices to reconnect without scanning first.

Resolvable Private Address (RPA) — 48 bits, rotates every 15 min, IRK-linked
01
2 MSBs
hash (24 bits) | prand (22 bits)
hash = AES-128(IRK, prand). Bonded device can verify by recomputing hash with its stored IRK.
Bits [47:46] = 01. The most useful type for privacy. Random to outsiders, but a device with the matching IRK can verify it. This is what gets used when LL Privacy is enabled.

8.17 — Chapter 8 Summary

What the BLE Link Layer Does — Everything Covered in Chapter 8

The link layer is the heart of BLE. Everything above it — L2CAP, ATT, GATT, GAP, profiles — depends on the link layer to create, maintain, and close the fundamental radio link. Chapter 8 covered every aspect of how it does this.

Architecture — Five States

  • Standby → default idle state
  • Advertising → broadcasts PDUs
  • Scanning → listens for PDUs
  • Initiating → sends CONNECT_REQ
  • Connection → data exchange
Simple 5-state machine → low silicon cost, low power
Channels & Hopping

  • 3 advertising channels (37/38/39)
  • 37 data channels for connections
  • AFH hop: f(n+1)=(fn+hop) mod 37
  • Channel map bitmap (37 bits)
  • Master updates map via LLCP
PDU Types

  • ADV_IND — connectable undirected
  • ADV_DIRECT_IND — reconnect
  • ADV_NONCONN_IND — beacon
  • ADV_SCAN_IND — scannable only
  • SCAN_REQ/RSP, CONNECT_REQ
  • Data PDU with SN/NESN ACK
LLCP Procedures

  • Connection & Channel Update
  • Encryption Start/Pause
  • Feature Exchange (bitmask)
  • Version Exchange
  • Termination (anytime)
  • LE Ping, Data Length (4.2)
Privacy & Filtering

  • RPA rotates every 15 minutes
  • IRK allows bonded device to resolve
  • Controller resolves (4.2, not Host)
  • White List filters by address
  • 3 filter policies (Adv/Scan/Init)
  • 4.2 extended scanner policies

The next chapter focuses on the HCI (Host Controller Interface) — the standardised command and event channel between the host software and the Bluetooth controller chip. Everything the host needs to control the link layer (start advertising, initiate connections, update parameters) is done through HCI commands, and everything the controller reports back (connection events, data arrival, disconnection) comes via HCI events.

Chapter 8 Complete — All Files
🔒

PDF 46

Privacy IRK, Resolving List,
Adv Filter Policy

PDF 79 (Here)

Scanner/Initiator Filter,
Sniffer, Summary
📡

PDF 1013

Chapter 9 — HCI Interface
& Commands

Chapter 8 Complete — On to Chapter 9: HCI

The Link Layer is fully covered. Chapter 9 covers the Host Controller Interface — how the host software talks to the Bluetooth controller chip using commands and events.

Next: Chapter 9 — HCI Interface → ← PDF 46: Privacy & White List

Leave a Reply

Your email address will not be published. Required fields are marked *