Bluetooth: controller: Refactor whitelisting

As a preparation for advanced filtering (Controller-based privacy) this
commit refactors whitelisting so that it becomes its own module and
actually correctly performs state tracking to avoid modifying the
whitelist when it's in use.

Additionally it also removes the duplicate separate entries for
advertising and scanning, since the specification only allows one single
global whitelist singleton.

Signed-off-by: Carles Cufi <carles.cufi@nordicsemi.no>
This commit is contained in:
Carles Cufi 2017-06-13 13:57:04 +02:00 committed by Anas Nashif
commit d0832f92fd
10 changed files with 157 additions and 99 deletions

View file

@ -494,17 +494,15 @@ static void le_read_wl_size(struct net_buf *buf, struct net_buf **evt)
rp = cmd_complete(evt, sizeof(*rp));
rp->status = 0x00;
rp->wl_size = 8;
rp->wl_size = ll_wl_size_get();
}
static void le_clear_wl(struct net_buf *buf, struct net_buf **evt)
{
struct bt_hci_evt_cc_status *ccst;
ll_filter_clear();
ccst = cmd_complete(evt, sizeof(*ccst));
ccst->status = 0x00;
ccst->status = ll_wl_clear();
}
static void le_add_dev_to_wl(struct net_buf *buf, struct net_buf **evt)
@ -513,10 +511,10 @@ static void le_add_dev_to_wl(struct net_buf *buf, struct net_buf **evt)
struct bt_hci_evt_cc_status *ccst;
u32_t status;
status = ll_filter_add(cmd->addr.type, &cmd->addr.a.val[0]);
status = ll_wl_add(&cmd->addr);
ccst = cmd_complete(evt, sizeof(*ccst));
ccst->status = (!status) ? 0x00 : BT_HCI_ERR_MEM_CAPACITY_EXCEEDED;
ccst->status = status;
}
static void le_rem_dev_from_wl(struct net_buf *buf, struct net_buf **evt)
@ -525,10 +523,10 @@ static void le_rem_dev_from_wl(struct net_buf *buf, struct net_buf **evt)
struct bt_hci_evt_cc_status *ccst;
u32_t status;
status = ll_filter_remove(cmd->addr.type, &cmd->addr.a.val[0]);
status = ll_wl_remove(&cmd->addr);
ccst = cmd_complete(evt, sizeof(*ccst));
ccst->status = (!status) ? 0x00 : BT_HCI_ERR_CMD_DISALLOWED;
ccst->status = status;
}
static void le_encrypt(struct net_buf *buf, struct net_buf **evt)

View file

@ -22,9 +22,11 @@ u32_t ll_adv_enable(u8_t enable);
u32_t ll_scan_params_set(u8_t type, u16_t interval, u16_t window,
u8_t own_addr_type, u8_t filter_policy);
u32_t ll_scan_enable(u8_t enable);
void ll_filter_clear(void);
u32_t ll_filter_add(u8_t addr_type, u8_t *addr);
u32_t ll_filter_remove(u8_t addr_type, u8_t *addr);
u32_t ll_wl_size_get(void);
u32_t ll_wl_clear(void);
u32_t ll_wl_add(bt_addr_le_t *addr);
u32_t ll_wl_remove(bt_addr_le_t *addr);
void ll_irk_clear(void);
u32_t ll_irk_add(u8_t *irk);

View file

@ -2,7 +2,7 @@ ccflags-y += -I$(srctree)/subsys/bluetooth/controller/include
ccflags-y += -I$(srctree)/subsys/bluetooth/controller
ccflags-y += -I$(srctree)/subsys/bluetooth
obj-y += crypto.o ctrl.o ll.o
obj-y += crypto.o ctrl.o ll.o ll_filter.o
obj-$(CONFIG_BLUETOOTH_BROADCASTER) += ll_adv.o
obj-$(CONFIG_BLUETOOTH_OBSERVER) += ll_scan.o
obj-$(CONFIG_BLUETOOTH_CENTRAL) += ll_master.o

View file

@ -33,6 +33,9 @@
#include "ctrl.h"
#include "ctrl_internal.h"
#include "ll.h"
#include "ll_filter.h"
#define BT_DBG_ENABLED IS_ENABLED(CONFIG_BLUETOOTH_DEBUG_HCI_DRIVER)
#include "common/log.h"
@ -80,10 +83,6 @@ struct advertiser {
u8_t chl_map_current:3;
u8_t filter_policy:2;
u8_t filter_enable_bitmask;
u8_t filter_addr_type_bitmask;
u8_t filter_bdaddr[8][BDADDR_SIZE];
struct radio_adv_data adv_data;
struct radio_adv_data scan_data;
@ -105,10 +104,6 @@ struct scanner {
u8_t init_addr[BDADDR_SIZE];
u32_t ticks_window;
u8_t filter_enable_bitmask;
u8_t filter_addr_type_bitmask;
u8_t filter_bdaddr[8][BDADDR_SIZE];
u16_t conn_interval;
u16_t conn_latency;
u16_t conn_timeout;
@ -131,10 +126,6 @@ static struct {
enum role volatile role;
enum state state;
u8_t filter_enable_bitmask;
u8_t filter_addr_type_bitmask;
u8_t filter_bdaddr[8][BDADDR_SIZE];
u8_t nirk;
u8_t irk[RADIO_IRK_COUNT_MAX][16];
@ -443,7 +434,6 @@ void ll_reset(void)
}
/* reset controller context members */
_radio.filter_enable_bitmask = 0;
_radio.nirk = 0;
_radio.advertiser.is_enabled = 0;
_radio.advertiser.conn = NULL;
@ -460,6 +450,8 @@ void ll_reset(void)
_radio.packet_release_first = 0;
_radio.packet_release_last = 0;
/* reset whitelist */
ll_wl_clear();
/* memory allocations */
common_init();
}
@ -4795,9 +4787,12 @@ static void event_adv(u32_t ticks_at_expire, u32_t remainder,
/* Setup Radio Filter */
if (_radio.advertiser.filter_policy) {
radio_filter_configure(_radio.advertiser.filter_enable_bitmask,
_radio.advertiser.filter_addr_type_bitmask,
(u8_t *)_radio.advertiser.filter_bdaddr);
struct ll_wl *wl = ctrl_wl_get();
radio_filter_configure(wl->enable_bitmask,
wl->addr_type_bitmask,
(u8_t *)wl->bdaddr);
}
radio_tmr_start(1,
@ -4982,10 +4977,12 @@ static void event_scan(u32_t ticks_at_expire, u32_t remainder, u16_t lazy,
/* Setup Radio Filter */
if (_radio.scanner.filter_policy) {
radio_filter_configure(_radio.scanner.filter_enable_bitmask,
_radio.scanner.filter_addr_type_bitmask,
(u8_t *)_radio.scanner.filter_bdaddr);
struct ll_wl *wl = ctrl_wl_get();
radio_filter_configure(wl->enable_bitmask,
wl->addr_type_bitmask,
(u8_t *)wl->bdaddr);
if (_radio.nirk) {
radio_ar_configure(_radio.nirk, _radio.irk);
}
@ -7745,56 +7742,6 @@ struct radio_adv_data *radio_scan_data_get(void)
return &_radio.advertiser.scan_data;
}
void ll_filter_clear(void)
{
_radio.filter_enable_bitmask = 0;
_radio.filter_addr_type_bitmask = 0;
}
u32_t ll_filter_add(u8_t addr_type, u8_t *addr)
{
if (_radio.filter_enable_bitmask != 0xFF) {
u8_t index;
for (index = 0;
(_radio.filter_enable_bitmask & (1 << index));
index++) {
}
_radio.filter_enable_bitmask |= (1 << index);
_radio.filter_addr_type_bitmask |=
((addr_type & 0x01) << index);
memcpy(&_radio.filter_bdaddr[index][0], addr, BDADDR_SIZE);
return 0;
}
return 1;
}
u32_t ll_filter_remove(u8_t addr_type, u8_t *addr)
{
u8_t index;
if (!_radio.filter_enable_bitmask) {
return 1;
}
index = 8;
while (index--) {
if ((_radio.filter_enable_bitmask & BIT(index)) &&
(((_radio.filter_addr_type_bitmask >> index) & 0x01) ==
(addr_type & 0x01)) &&
!memcmp(_radio.filter_bdaddr[index], addr, BDADDR_SIZE)) {
_radio.filter_enable_bitmask &= ~BIT(index);
_radio.filter_addr_type_bitmask &= ~BIT(index);
return 0;
}
}
return 1;
}
void ll_irk_clear(void)
{
_radio.nirk = 0;
@ -8172,15 +8119,6 @@ u32_t radio_adv_enable(u16_t interval, u8_t chl_map, u8_t filter_policy)
_radio.advertiser.chl_map = chl_map;
_radio.advertiser.filter_policy = filter_policy;
if (filter_policy) {
_radio.advertiser.filter_addr_type_bitmask =
_radio.filter_addr_type_bitmask;
memcpy(&_radio.advertiser.filter_bdaddr[0][0],
&_radio.filter_bdaddr[0][0],
sizeof(_radio.advertiser.filter_bdaddr));
_radio.advertiser.filter_enable_bitmask =
_radio.filter_enable_bitmask;
}
_radio.advertiser.hdr.ticks_active_to_start =
_radio.ticks_active_to_start;
@ -8335,15 +8273,6 @@ u32_t radio_scan_enable(u8_t type, u8_t init_addr_type, u8_t *init_addr,
_radio.scanner.ticks_window =
TICKER_US_TO_TICKS((u64_t) window * 625);
_radio.scanner.filter_policy = filter_policy;
if (filter_policy) {
_radio.scanner.filter_addr_type_bitmask =
_radio.filter_addr_type_bitmask;
memcpy(&_radio.scanner.filter_bdaddr[0][0],
&_radio.filter_bdaddr[0][0],
sizeof(_radio.scanner.filter_bdaddr));
_radio.scanner.filter_enable_bitmask =
_radio.filter_enable_bitmask;
}
_radio.scanner.hdr.ticks_active_to_start =
_radio.ticks_active_to_start;

View file

@ -14,6 +14,7 @@
#ifdef CONFIG_CLOCK_CONTROL_NRF5
#include <drivers/clock_control/nrf5_clock_control.h>
#endif
#include <bluetooth/hci.h>
#define BT_DBG_ENABLED IS_ENABLED(CONFIG_BLUETOOTH_DEBUG_HCI_DRIVER)
#include "common/log.h"

View file

@ -8,6 +8,7 @@
#include <string.h>
#include <zephyr.h>
#include <bluetooth/hci.h>
#include "util/util.h"

View file

@ -0,0 +1,108 @@
/*
* Copyright (c) 2017 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <string.h>
#include <zephyr.h>
#include <bluetooth/hci.h>
#include "util/util.h"
#include "pdu.h"
#include "ctrl.h"
#include "ll.h"
#include "ll_filter.h"
#define ADDR_TYPE_ANON 0xFF
#define BT_DBG_ENABLED IS_ENABLED(CONFIG_BLUETOOTH_DEBUG_HCI_DRIVER)
#include "common/log.h"
static struct ll_wl wl;
struct ll_wl *ctrl_wl_get(void)
{
return &wl;
}
u32_t ll_wl_size_get(void)
{
return WL_SIZE;
}
u32_t ll_wl_clear(void)
{
if (radio_adv_filter_pol_get() || (radio_scan_filter_pol_get() & 0x1)) {
return BT_HCI_ERR_CMD_DISALLOWED;
}
wl.enable_bitmask = 0;
wl.addr_type_bitmask = 0;
wl.anon = 0;
return 0;
}
u32_t ll_wl_add(bt_addr_le_t *addr)
{
u8_t index;
if (radio_adv_filter_pol_get() || (radio_scan_filter_pol_get() & 0x1)) {
return BT_HCI_ERR_CMD_DISALLOWED;
}
if (addr->type == ADDR_TYPE_ANON) {
wl.anon = 1;
return 0;
}
if (wl.enable_bitmask == 0xFF) {
return BT_HCI_ERR_MEM_CAPACITY_EXCEEDED;
}
for (index = 0;
(wl.enable_bitmask & (1 << index));
index++) {
}
wl.enable_bitmask |= (1 << index);
wl.addr_type_bitmask |= ((addr->type & 0x01) << index);
memcpy(&wl.bdaddr[index][0], addr->a.val, BDADDR_SIZE);
return 0;
}
u32_t ll_wl_remove(bt_addr_le_t *addr)
{
u8_t index;
if (radio_adv_filter_pol_get() || (radio_scan_filter_pol_get() & 0x1)) {
return BT_HCI_ERR_CMD_DISALLOWED;
}
if (addr->type == ADDR_TYPE_ANON) {
wl.anon = 0;
return 0;
}
if (!wl.enable_bitmask) {
return BT_HCI_ERR_INVALID_PARAM;
}
index = 8;
while (index--) {
if ((wl.enable_bitmask & BIT(index)) &&
(((wl.addr_type_bitmask >> index) & 0x01) ==
(addr->type & 0x01)) &&
!memcmp(wl.bdaddr[index], addr->a.val, BDADDR_SIZE)) {
wl.enable_bitmask &= ~BIT(index);
wl.addr_type_bitmask &= ~BIT(index);
return 0;
}
}
return BT_HCI_ERR_INVALID_PARAM;
}

View file

@ -0,0 +1,17 @@
/*
* Copyright (c) 2017 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: Apache-2.0
*/
#define WL_SIZE 8
struct ll_wl {
u8_t enable_bitmask;
u8_t addr_type_bitmask;
u8_t bdaddr[WL_SIZE][BDADDR_SIZE];
u8_t anon;
};
struct ll_wl *ctrl_wl_get(void);

View file

@ -6,6 +6,7 @@
*/
#include <zephyr.h>
#include <bluetooth/hci.h>
#include "util/util.h"

View file

@ -6,6 +6,7 @@
*/
#include <zephyr.h>
#include <bluetooth/hci.h>
#include "util/util.h"