Bluetooth: controller: Fix directed adv filtering

The specification states that filter policies shall be ignored for
directed advertising, so reflect this behaviour in the code.
Additionally when the local device is using RPAs but the peer uses an
identity address, the resolving list index needs to be updated when
traversing the RL to reflect that there has indeed been a  device match
even though the IRK match did not happen.

Signed-off-by: Carles Cufi <carles.cufi@nordicsemi.no>
This commit is contained in:
Carles Cufi 2017-07-12 09:48:12 +02:00
commit 7b02b06b41
3 changed files with 29 additions and 18 deletions

View file

@ -713,13 +713,13 @@ static u32_t isr_rx_adv_sr_report(struct pdu_adv *pdu_adv_rx, u8_t rssi_ready)
#endif /* CONFIG_BLUETOOTH_CONTROLLER_SCAN_REQ_NOTIFY */
static inline bool isr_adv_sr_check(struct pdu_adv *pdu, u8_t devmatch_ok,
u8_t rl_idx)
u8_t *rl_idx)
{
#if defined(CONFIG_BLUETOOTH_CONTROLLER_PRIVACY)
return ((((_radio.advertiser.filter_policy & 0x01) == 0) &&
ctrl_rl_allowed(pdu->tx_addr,
pdu->payload.scan_req.scan_addr)) ||
(devmatch_ok) || (ctrl_irk_whitelisted(rl_idx))) &&
pdu->payload.scan_req.scan_addr, rl_idx)) ||
(devmatch_ok) || (ctrl_irk_whitelisted(*rl_idx))) &&
(1 /** @todo own addr match check */);
#else
return (((_radio.advertiser.filter_policy & 0x01) == 0) ||
@ -731,10 +731,6 @@ static inline bool isr_adv_sr_check(struct pdu_adv *pdu, u8_t devmatch_ok,
static inline bool isr_adv_ci_tgta_check(struct pdu_adv *adv, struct pdu_adv *ci,
u8_t rl_idx)
{
if (adv->type != PDU_ADV_TYPE_DIRECT_IND) {
return true;
}
#if defined(CONFIG_BLUETOOTH_CONTROLLER_PRIVACY)
if (rl_idx != FILTER_IDX_NONE) {
return rl_idx == _radio.advertiser.rl_idx;
@ -757,20 +753,30 @@ static inline bool isr_adv_ci_adva_check(struct pdu_adv *adv,
}
static inline bool isr_adv_ci_check(struct pdu_adv *adv, struct pdu_adv *ci,
u8_t devmatch_ok, u8_t rl_idx)
u8_t devmatch_ok, u8_t *rl_idx)
{
/* LL 4.3.2: filter policy shall be ignored for directed adv */
if (adv->type == PDU_ADV_TYPE_DIRECT_IND) {
#if defined(CONFIG_BLUETOOTH_CONTROLLER_PRIVACY)
return ctrl_rl_allowed(ci->tx_addr,
ci->payload.connect_ind.init_addr, rl_idx) &&
#else
return (1) &&
#endif
isr_adv_ci_adva_check(adv, ci) &&
isr_adv_ci_tgta_check(adv, ci, *rl_idx);
}
#if defined(CONFIG_BLUETOOTH_CONTROLLER_PRIVACY)
return ((((_radio.advertiser.filter_policy & 0x02) == 0) &&
ctrl_rl_allowed(ci->tx_addr,
ci->payload.connect_ind.init_addr)) ||
(devmatch_ok) || (ctrl_irk_whitelisted(rl_idx))) &&
isr_adv_ci_adva_check(adv, ci) &&
isr_adv_ci_tgta_check(adv, ci, rl_idx);
ci->payload.connect_ind.init_addr, rl_idx)) ||
(devmatch_ok) || (ctrl_irk_whitelisted(*rl_idx))) &&
isr_adv_ci_adva_check(adv, ci);
#else
return (((_radio.advertiser.filter_policy & 0x02) == 0) ||
(devmatch_ok)) &&
isr_adv_ci_adva_check(adv, ci) &&
isr_adv_ci_tgta_check(adv, ci, rl_idx);
isr_adv_ci_adva_check(adv, ci);
#endif
}
@ -792,7 +798,7 @@ static inline u32_t isr_rx_adv(u8_t devmatch_ok, u8_t devmatch_id,
if ((pdu_adv->type == PDU_ADV_TYPE_SCAN_REQ) &&
(pdu_adv->len == sizeof(struct pdu_adv_payload_scan_req)) &&
isr_adv_sr_check(pdu_adv, devmatch_ok, rl_idx)) {
isr_adv_sr_check(pdu_adv, devmatch_ok, &rl_idx)) {
#if defined(CONFIG_BLUETOOTH_CONTROLLER_SCAN_REQ_NOTIFY)
if (!IS_ENABLED(CONFIG_BLUETOOTH_CONTROLLER_ADV_EXT) ||
@ -818,7 +824,7 @@ static inline u32_t isr_rx_adv(u8_t devmatch_ok, u8_t devmatch_id,
return 0;
} else if ((pdu_adv->type == PDU_ADV_TYPE_CONNECT_IND) &&
(pdu_adv->len == sizeof(struct pdu_adv_payload_connect_ind)) &&
isr_adv_ci_check(_pdu_adv, pdu_adv, devmatch_ok, rl_idx) &&
isr_adv_ci_check(_pdu_adv, pdu_adv, devmatch_ok, &rl_idx) &&
((_radio.fc_ena == 0) || (_radio.fc_req == _radio.fc_ack)) &&
(_radio.advertiser.conn)) {
struct radio_le_conn_cmplt *radio_le_conn_cmplt;

View file

@ -397,7 +397,7 @@ u8_t ll_rl_find(u8_t id_addr_type, u8_t *id_addr, u8_t *free)
return FILTER_IDX_NONE;
}
bool ctrl_rl_allowed(u8_t id_addr_type, u8_t *id_addr)
bool ctrl_rl_allowed(u8_t id_addr_type, u8_t *id_addr, u8_t *rl_idx)
{
int i, j;
@ -415,6 +415,11 @@ bool ctrl_rl_allowed(u8_t id_addr_type, u8_t *id_addr)
}
if (j == BDADDR_SIZE) {
if (*rl_idx == FILTER_IDX_NONE) {
*rl_idx = i;
} else {
LL_ASSERT(*rl_idx == i);
}
return !rl[i].pirk || rl[i].dev;
}
}

View file

@ -27,5 +27,5 @@ bool ctrl_rl_enabled(void);
void ll_rl_rpa_update(bool timeout);
u8_t ll_rl_find(u8_t id_addr_type, u8_t *id_addr, u8_t *free);
bool ctrl_rl_allowed(u8_t id_addr_type, u8_t *id_addr);
bool ctrl_rl_allowed(u8_t id_addr_type, u8_t *id_addr, u8_t *rl_idx);
void ll_rl_pdu_adv_update(int idx, struct pdu_adv *pdu);