Compare commits
24 Commits
v2.6.0
...
v2.4-branc
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fff583d699 | ||
|
|
edf6be2986 | ||
|
|
af4148c8c8 | ||
|
|
b35d6d4f4d | ||
|
|
d14ba3c1b0 | ||
|
|
fab3f949b5 | ||
|
|
f911248d92 | ||
|
|
029b8a597c | ||
|
|
2e30f2abea | ||
|
|
cf3b638fcb | ||
|
|
de142e438d | ||
|
|
0a14470645 | ||
|
|
da887af568 | ||
|
|
705ff30071 | ||
|
|
3a06d3d523 | ||
|
|
3c1fb27e9c | ||
|
|
9c30e79469 | ||
|
|
463bf8eadc | ||
|
|
951786950c | ||
|
|
75ebb69b1e | ||
|
|
a40d31b153 | ||
|
|
c2a0b0f50b | ||
|
|
60c27beb03 | ||
|
|
e8f0ec6e73 |
2
.github/workflows/doc-build.yml
vendored
2
.github/workflows/doc-build.yml
vendored
@@ -12,7 +12,7 @@ jobs:
|
||||
steps:
|
||||
- name: Update PATH for west
|
||||
run: |
|
||||
echo "::add-path::$HOME/.local/bin"
|
||||
echo "$HOME/.local/bin" >> $GITHUB_PATH
|
||||
|
||||
- name: checkout
|
||||
uses: actions/checkout@v2
|
||||
|
||||
2
.github/workflows/doc-publish.yml
vendored
2
.github/workflows/doc-publish.yml
vendored
@@ -18,7 +18,7 @@ jobs:
|
||||
steps:
|
||||
- name: Update PATH for west
|
||||
run: |
|
||||
echo "::add-path::$HOME/.local/bin"
|
||||
echo "$HOME/.local/bin" >> $GITHUB_PATH
|
||||
|
||||
- name: Determine tag
|
||||
id: tag
|
||||
|
||||
@@ -625,7 +625,7 @@ static int dps310_init(const struct device *dev)
|
||||
uint8_t tmp_coef_srce = 0;
|
||||
|
||||
res = i2c_write_read(data->i2c_master, config->i2c_addr,
|
||||
®_ADDR_COEF_SRCE, 1, &tmp_coef_srce, 18);
|
||||
®_ADDR_COEF_SRCE, 1, &tmp_coef_srce, sizeof(tmp_coef_srce));
|
||||
if (res < 0) {
|
||||
LOG_WRN("I2C error: %d", res);
|
||||
return -EIO;
|
||||
|
||||
@@ -128,7 +128,7 @@ extern "C" {
|
||||
Z_DEVICE_DEFINE_PM(dev_name) \
|
||||
static const Z_DECL_ALIGN(struct device) \
|
||||
DEVICE_NAME_GET(dev_name) __used \
|
||||
__attribute__((__section__(".device_" #level STRINGIFY(prio)))) = { \
|
||||
__attribute__((__section__(".device_" #level STRINGIFY(prio)"_"))) = { \
|
||||
.name = drv_name, \
|
||||
.config = (cfg_ptr), \
|
||||
.api = (api_ptr), \
|
||||
|
||||
@@ -85,7 +85,7 @@ void z_sys_init_run_level(int32_t _level);
|
||||
#define Z_INIT_ENTRY_DEFINE(_entry_name, _init_fn, _device, _level, _prio) \
|
||||
static const Z_DECL_ALIGN(struct init_entry) \
|
||||
_CONCAT(__init_, _entry_name) __used \
|
||||
__attribute__((__section__(".init_" #_level STRINGIFY(_prio)))) = { \
|
||||
__attribute__((__section__(".init_" #_level STRINGIFY(_prio)"_"))) = { \
|
||||
.init = (_init_fn), \
|
||||
.dev = (_device), \
|
||||
}
|
||||
|
||||
@@ -116,8 +116,8 @@
|
||||
*/
|
||||
#define CREATE_OBJ_LEVEL(object, level) \
|
||||
__##object##_##level##_start = .; \
|
||||
KEEP(*(SORT(.object##_##level[0-9]*))); \
|
||||
KEEP(*(SORT(.object##_##level[1-9][0-9]*)));
|
||||
KEEP(*(SORT(.object##_##level[0-9]_*))); \
|
||||
KEEP(*(SORT(.object##_##level[1-9][0-9]_*)));
|
||||
|
||||
/*
|
||||
* link in shell initialization objects for all modules that use shell and
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include <sys/mempool_base.h>
|
||||
#include <sys/mempool.h>
|
||||
#include <sys/check.h>
|
||||
#include <sys/math_extras.h>
|
||||
|
||||
#ifdef CONFIG_MISRA_SANE
|
||||
#define LVL_ARRAY_SZ(n) (8 * sizeof(void *) / 2)
|
||||
@@ -336,7 +337,12 @@ void *sys_mem_pool_alloc(struct sys_mem_pool *p, size_t size)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
size += WB_UP(sizeof(struct sys_mem_pool_block));
|
||||
if (size_add_overflow(size, WB_UP(sizeof(struct sys_mem_pool_block)),
|
||||
&size)) {
|
||||
ret = NULL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (z_sys_mem_pool_block_alloc(&p->base, size, &level, &block,
|
||||
(void **)&ret)) {
|
||||
ret = NULL;
|
||||
|
||||
@@ -64,10 +64,27 @@ int lll_clock_init(void)
|
||||
|
||||
int lll_clock_wait(void)
|
||||
{
|
||||
struct onoff_manager *mgr =
|
||||
z_nrf_clock_control_get_onoff(CLOCK_CONTROL_NRF_SUBSYS_LF);
|
||||
struct onoff_manager *mgr;
|
||||
static bool done;
|
||||
int err;
|
||||
|
||||
return blocking_on(mgr, LFCLOCK_TIMEOUT_MS);
|
||||
if (done) {
|
||||
return 0;
|
||||
}
|
||||
done = true;
|
||||
|
||||
mgr = z_nrf_clock_control_get_onoff(CLOCK_CONTROL_NRF_SUBSYS_LF);
|
||||
err = blocking_on(mgr, LFCLOCK_TIMEOUT_MS);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
|
||||
err = onoff_release(mgr);
|
||||
if (err != ONOFF_STATE_ON) {
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int lll_hfclock_on(void)
|
||||
|
||||
@@ -650,7 +650,8 @@ static inline int isr_rx_pdu(struct lll_conn *lll, struct pdu_data *pdu_data_rx,
|
||||
lll->empty = 0;
|
||||
|
||||
pdu_data_tx = (void *)radio_pkt_empty_get();
|
||||
if (IS_ENABLED(CONFIG_BT_CENTRAL) && !lll->role) {
|
||||
if (IS_ENABLED(CONFIG_BT_CENTRAL) && !lll->role &&
|
||||
!pdu_data_rx->md) {
|
||||
*is_done = !pdu_data_tx->md;
|
||||
}
|
||||
|
||||
@@ -693,7 +694,8 @@ static inline int isr_rx_pdu(struct lll_conn *lll, struct pdu_data *pdu_data_rx,
|
||||
*tx_release = tx;
|
||||
}
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_CENTRAL) && !lll->role) {
|
||||
if (IS_ENABLED(CONFIG_BT_CENTRAL) && !lll->role &&
|
||||
!pdu_data_rx->md) {
|
||||
*is_done = !pdu_data_tx->md;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1690,6 +1690,11 @@ static void conn_cleanup(struct ll_conn *conn, uint8_t reason)
|
||||
struct node_rx_pdu *rx;
|
||||
uint32_t ticker_status;
|
||||
|
||||
/* reset mutex */
|
||||
if (conn == conn_upd_curr) {
|
||||
ull_conn_upd_curr_reset();
|
||||
}
|
||||
|
||||
/* Only termination structure is populated here in ULL context
|
||||
* but the actual enqueue happens in the LLL context in
|
||||
* tx_lll_flush. The reason being to avoid passing the reason
|
||||
|
||||
@@ -36,7 +36,7 @@ config BT_ATT_TX_MAX
|
||||
|
||||
config BT_EATT
|
||||
bool "Enhanced ATT Bearers support [EXPERIMENTAL]"
|
||||
depends on BT_L2CAP_DYNAMIC_CHANNEL
|
||||
depends on BT_L2CAP_ECRED
|
||||
help
|
||||
This option enables support for Enhanced ATT bearers support. When
|
||||
enabled additional L2CAP channels can be connected as bearers enabling
|
||||
|
||||
@@ -56,6 +56,13 @@ config BT_L2CAP_DYNAMIC_CHANNEL
|
||||
This option enables support for LE Connection oriented Channels,
|
||||
allowing the creation of dynamic L2CAP Channels.
|
||||
|
||||
config BT_L2CAP_ECRED
|
||||
bool "L2CAP Enhanced Credit Based Flow Control support"
|
||||
depends on BT_L2CAP_DYNAMIC_CHANNEL
|
||||
help
|
||||
This option enables support for LE Connection oriented Channels with
|
||||
Enhanced Credit Based Flow Control support on dynamic L2CAP Channels.
|
||||
|
||||
config BT_DEBUG_L2CAP
|
||||
bool "Bluetooth L2CAP debug"
|
||||
depends on BT_DEBUG
|
||||
|
||||
@@ -2699,7 +2699,7 @@ static void bt_att_encrypt_change(struct bt_l2cap_chan *chan,
|
||||
* outstanding request about security failure.
|
||||
*/
|
||||
if (hci_status) {
|
||||
if (att_chan->req) {
|
||||
if (att_chan->req && att_chan->req->retrying) {
|
||||
att_handle_rsp(att_chan, NULL, 0,
|
||||
BT_ATT_ERR_AUTHENTICATION);
|
||||
}
|
||||
@@ -2713,7 +2713,7 @@ static void bt_att_encrypt_change(struct bt_l2cap_chan *chan,
|
||||
return;
|
||||
}
|
||||
|
||||
if (!att_chan->req || !att_chan->req->retrying) {
|
||||
if (!(att_chan->req && att_chan->req->retrying)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -29,6 +29,7 @@ config BT_AUDIO_UNICAST
|
||||
select BT_ISO
|
||||
select BT_GATT_DYNAMIC_DB
|
||||
select BT_GATT_CACHING
|
||||
select BT_L2CAP_ECRED
|
||||
select BT_EATT
|
||||
help
|
||||
This option enables support for Bluetooth Unicast Audio using
|
||||
|
||||
@@ -4339,11 +4339,6 @@ next:
|
||||
static int ccc_set(const char *name, size_t len_rd, settings_read_cb read_cb,
|
||||
void *cb_arg)
|
||||
{
|
||||
if (IS_ENABLED(CONFIG_BT_SETTINGS_CCC_LAZY_LOADING)) {
|
||||
/* Only load CCCs on demand */
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
|
||||
struct ccc_store ccc_store[CCC_STORE_MAX];
|
||||
struct ccc_load load;
|
||||
@@ -4401,7 +4396,18 @@ static int ccc_set(const char *name, size_t len_rd, settings_read_cb read_cb,
|
||||
return 0;
|
||||
}
|
||||
|
||||
SETTINGS_STATIC_HANDLER_DEFINE(bt_ccc, "bt/ccc", NULL, ccc_set, NULL, NULL);
|
||||
static int ccc_set_cb(const char *name, size_t len_rd, settings_read_cb read_cb,
|
||||
void *cb_arg)
|
||||
{
|
||||
if (IS_ENABLED(CONFIG_BT_SETTINGS_CCC_LAZY_LOADING)) {
|
||||
/* Only load CCCs on demand */
|
||||
return 0;
|
||||
}
|
||||
|
||||
return ccc_set(name, len_rd, read_cb, cb_arg);
|
||||
}
|
||||
|
||||
SETTINGS_STATIC_HANDLER_DEFINE(bt_ccc, "bt/ccc", NULL, ccc_set_cb, NULL, NULL);
|
||||
|
||||
static int ccc_set_direct(const char *key, size_t len, settings_read_cb read_cb,
|
||||
void *cb_arg, void *param)
|
||||
|
||||
@@ -466,6 +466,7 @@ static int l2cap_le_conn_req(struct bt_l2cap_le_chan *ch)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_BT_L2CAP_ECRED)
|
||||
static int l2cap_ecred_conn_req(struct bt_l2cap_chan **chan, int channels)
|
||||
{
|
||||
struct net_buf *buf;
|
||||
@@ -506,6 +507,7 @@ static int l2cap_ecred_conn_req(struct bt_l2cap_chan **chan, int channels)
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif /* defined(CONFIG_BT_L2CAP_ECRED) */
|
||||
|
||||
static void l2cap_le_encrypt_change(struct bt_l2cap_chan *chan, uint8_t status)
|
||||
{
|
||||
@@ -521,6 +523,7 @@ static void l2cap_le_encrypt_change(struct bt_l2cap_chan *chan, uint8_t status)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_BT_L2CAP_ECRED)
|
||||
if (chan->ident) {
|
||||
struct bt_l2cap_chan *echan[L2CAP_ECRED_CHAN_MAX];
|
||||
struct bt_l2cap_le_chan *ch;
|
||||
@@ -534,6 +537,7 @@ static void l2cap_le_encrypt_change(struct bt_l2cap_chan *chan, uint8_t status)
|
||||
l2cap_ecred_conn_req(echan, i);
|
||||
return;
|
||||
}
|
||||
#endif /* defined(CONFIG_BT_L2CAP_ECRED) */
|
||||
|
||||
/* Retry to connect */
|
||||
err = l2cap_le_conn_req(BT_L2CAP_LE_CHAN(chan));
|
||||
@@ -1078,6 +1082,7 @@ rsp:
|
||||
bt_l2cap_send(conn, BT_L2CAP_CID_LE_SIG, buf);
|
||||
}
|
||||
|
||||
#if defined(CONFIG_BT_L2CAP_ECRED)
|
||||
static void le_ecred_conn_req(struct bt_l2cap *l2cap, uint8_t ident,
|
||||
struct net_buf *buf)
|
||||
{
|
||||
@@ -1098,6 +1103,13 @@ static void le_ecred_conn_req(struct bt_l2cap *l2cap, uint8_t ident,
|
||||
}
|
||||
|
||||
req = net_buf_pull_mem(buf, sizeof(*req));
|
||||
|
||||
if (buf->len > sizeof(dcid)) {
|
||||
BT_ERR("Too large LE conn req packet size");
|
||||
result = BT_L2CAP_LE_ERR_INVALID_PARAMS;
|
||||
goto response;
|
||||
}
|
||||
|
||||
psm = sys_le16_to_cpu(req->psm);
|
||||
mtu = sys_le16_to_cpu(req->mtu);
|
||||
mps = sys_le16_to_cpu(req->mps);
|
||||
@@ -1124,6 +1136,8 @@ static void le_ecred_conn_req(struct bt_l2cap *l2cap, uint8_t ident,
|
||||
goto response;
|
||||
}
|
||||
|
||||
memset(dcid, 0, sizeof(dcid));
|
||||
|
||||
while (buf->len >= sizeof(scid)) {
|
||||
scid = net_buf_pull_le16(buf);
|
||||
|
||||
@@ -1135,28 +1149,20 @@ static void le_ecred_conn_req(struct bt_l2cap *l2cap, uint8_t ident,
|
||||
dcid[i++] = sys_cpu_to_le16(ch->rx.cid);
|
||||
continue;
|
||||
/* Some connections refused – invalid Source CID */
|
||||
case BT_L2CAP_LE_ERR_INVALID_SCID:
|
||||
/* Some connections refused – Source CID already allocated */
|
||||
case BT_L2CAP_LE_ERR_SCID_IN_USE:
|
||||
/* Some connections refused – not enough resources
|
||||
* available.
|
||||
*/
|
||||
default:
|
||||
/* If a Destination CID is 0x0000, the channel was not
|
||||
* established.
|
||||
*/
|
||||
dcid[i++] = 0x0000;
|
||||
continue;
|
||||
/* Some connections refused – not enough resources
|
||||
* available.
|
||||
*/
|
||||
case BT_L2CAP_LE_ERR_NO_RESOURCES:
|
||||
default:
|
||||
goto response;
|
||||
}
|
||||
}
|
||||
|
||||
response:
|
||||
if (!i) {
|
||||
i = buf->len / sizeof(scid);
|
||||
}
|
||||
|
||||
buf = l2cap_create_le_sig_pdu(buf, BT_L2CAP_ECRED_CONN_RSP, ident,
|
||||
sizeof(*rsp) + (sizeof(scid) * i));
|
||||
|
||||
@@ -1254,6 +1260,7 @@ response:
|
||||
|
||||
bt_l2cap_send(conn, BT_L2CAP_CID_LE_SIG, buf);
|
||||
}
|
||||
#endif /* defined(CONFIG_BT_L2CAP_ECRED) */
|
||||
|
||||
static struct bt_l2cap_le_chan *l2cap_remove_rx_cid(struct bt_conn *conn,
|
||||
uint16_t cid)
|
||||
@@ -1367,6 +1374,7 @@ static int l2cap_change_security(struct bt_l2cap_le_chan *chan, uint16_t err)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_BT_L2CAP_ECRED)
|
||||
static void le_ecred_conn_rsp(struct bt_l2cap *l2cap, uint8_t ident,
|
||||
struct net_buf *buf)
|
||||
{
|
||||
@@ -1473,6 +1481,7 @@ static void le_ecred_conn_rsp(struct bt_l2cap *l2cap, uint8_t ident,
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_BT_L2CAP_ECRED */
|
||||
|
||||
static void le_conn_rsp(struct bt_l2cap *l2cap, uint8_t ident,
|
||||
struct net_buf *buf)
|
||||
@@ -1920,6 +1929,7 @@ static int l2cap_recv(struct bt_l2cap_chan *chan, struct net_buf *buf)
|
||||
case BT_L2CAP_CMD_REJECT:
|
||||
reject_cmd(l2cap, hdr->ident, buf);
|
||||
break;
|
||||
#if defined(CONFIG_BT_L2CAP_ECRED)
|
||||
case BT_L2CAP_ECRED_CONN_REQ:
|
||||
le_ecred_conn_req(l2cap, hdr->ident, buf);
|
||||
break;
|
||||
@@ -1929,6 +1939,7 @@ static int l2cap_recv(struct bt_l2cap_chan *chan, struct net_buf *buf)
|
||||
case BT_L2CAP_ECRED_RECONF_REQ:
|
||||
le_ecred_reconf_req(l2cap, hdr->ident, buf);
|
||||
break;
|
||||
#endif /* defined(CONFIG_BT_L2CAP_ECRED) */
|
||||
#else
|
||||
case BT_L2CAP_CMD_REJECT:
|
||||
/* Ignored */
|
||||
@@ -2175,6 +2186,12 @@ static void l2cap_chan_le_recv(struct bt_l2cap_le_chan *chan,
|
||||
return;
|
||||
}
|
||||
|
||||
if (buf->len < 2) {
|
||||
BT_WARN("Too short data packet");
|
||||
bt_l2cap_chan_disconnect(&chan->chan);
|
||||
return;
|
||||
}
|
||||
|
||||
sdu_len = net_buf_pull_le16(buf);
|
||||
|
||||
BT_DBG("chan %p len %u sdu_len %u", chan, buf->len, sdu_len);
|
||||
@@ -2403,6 +2420,7 @@ fail:
|
||||
return err;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_BT_L2CAP_ECRED)
|
||||
static int l2cap_ecred_init(struct bt_conn *conn,
|
||||
struct bt_l2cap_le_chan *ch, uint16_t psm)
|
||||
{
|
||||
@@ -2463,6 +2481,7 @@ fail:
|
||||
|
||||
return err;
|
||||
}
|
||||
#endif /* defined(CONFIG_BT_L2CAP_ECRED) */
|
||||
|
||||
int bt_l2cap_chan_connect(struct bt_conn *conn, struct bt_l2cap_chan *chan,
|
||||
uint16_t psm)
|
||||
|
||||
@@ -737,14 +737,8 @@ static uint8_t get_encryption_key_size(struct bt_smp *smp)
|
||||
/* Check that if a new pairing procedure with an existing bond will not lower
|
||||
* the established security level of the bond.
|
||||
*/
|
||||
static bool update_keys_check(struct bt_smp *smp)
|
||||
static bool update_keys_check(struct bt_smp *smp, struct bt_keys *keys)
|
||||
{
|
||||
struct bt_conn *conn = smp->chan.chan.conn;
|
||||
|
||||
if (!conn->le.keys) {
|
||||
conn->le.keys = bt_keys_get_addr(conn->id, &conn->le.dst);
|
||||
}
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_SMP_DISABLE_LEGACY_JW_PASSKEY) &&
|
||||
!atomic_test_bit(smp->flags, SMP_FLAG_SC) &&
|
||||
smp->method != LEGACY_OOB) {
|
||||
@@ -756,27 +750,27 @@ static bool update_keys_check(struct bt_smp *smp)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!conn->le.keys ||
|
||||
!(conn->le.keys->keys & (BT_KEYS_LTK_P256 | BT_KEYS_LTK))) {
|
||||
if (!keys ||
|
||||
!(keys->keys & (BT_KEYS_LTK_P256 | BT_KEYS_LTK))) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (conn->le.keys->enc_size > get_encryption_key_size(smp)) {
|
||||
if (keys->enc_size > get_encryption_key_size(smp)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((conn->le.keys->keys & BT_KEYS_LTK_P256) &&
|
||||
if ((keys->keys & BT_KEYS_LTK_P256) &&
|
||||
!atomic_test_bit(smp->flags, SMP_FLAG_SC)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((conn->le.keys->flags & BT_KEYS_AUTHENTICATED) &&
|
||||
if ((keys->flags & BT_KEYS_AUTHENTICATED) &&
|
||||
smp->method == JUST_WORKS) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!IS_ENABLED(CONFIG_BT_SMP_ALLOW_UNAUTH_OVERWRITE) &&
|
||||
(!(conn->le.keys->flags & BT_KEYS_AUTHENTICATED)
|
||||
(!(keys->flags & BT_KEYS_AUTHENTICATED)
|
||||
&& smp->method == JUST_WORKS)) {
|
||||
return false;
|
||||
}
|
||||
@@ -2938,7 +2932,7 @@ static uint8_t smp_pairing_req(struct bt_smp *smp, struct net_buf *buf)
|
||||
|
||||
smp->method = get_pair_method(smp, req->io_capability);
|
||||
|
||||
if (!update_keys_check(smp)) {
|
||||
if (!update_keys_check(smp, conn->le.keys)) {
|
||||
return BT_SMP_ERR_AUTH_REQUIREMENTS;
|
||||
}
|
||||
|
||||
@@ -3139,7 +3133,7 @@ static uint8_t smp_pairing_rsp(struct bt_smp *smp, struct net_buf *buf)
|
||||
|
||||
smp->method = get_pair_method(smp, rsp->io_capability);
|
||||
|
||||
if (!update_keys_check(smp)) {
|
||||
if (!update_keys_check(smp, conn->le.keys)) {
|
||||
return BT_SMP_ERR_AUTH_REQUIREMENTS;
|
||||
}
|
||||
|
||||
@@ -3737,6 +3731,18 @@ static uint8_t smp_ident_addr_info(struct bt_smp *smp, struct net_buf *buf)
|
||||
return BT_SMP_ERR_INVALID_PARAMS;
|
||||
}
|
||||
|
||||
if (bt_addr_le_cmp(&conn->le.dst, &req->addr) != 0) {
|
||||
struct bt_keys *keys = bt_keys_find_addr(conn->id, &req->addr);
|
||||
|
||||
if (keys) {
|
||||
if (!update_keys_check(smp, keys)) {
|
||||
return BT_SMP_ERR_UNSPECIFIED;
|
||||
}
|
||||
|
||||
bt_keys_clear(keys);
|
||||
}
|
||||
}
|
||||
|
||||
if (atomic_test_bit(smp->flags, SMP_FLAG_BOND)) {
|
||||
const bt_addr_le_t *dst;
|
||||
struct bt_keys *keys;
|
||||
|
||||
@@ -178,6 +178,12 @@ void bt_mesh_reset(void)
|
||||
bt_mesh_rx_reset();
|
||||
bt_mesh_tx_reset();
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
|
||||
bt_mesh_clear_rpl();
|
||||
} else {
|
||||
(void)memset(bt_mesh.rpl, 0, sizeof(bt_mesh.rpl));
|
||||
}
|
||||
|
||||
bt_mesh_net_loopback_clear(BT_MESH_KEY_ANY);
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_MESH_LOW_POWER)) {
|
||||
|
||||
@@ -1821,12 +1821,6 @@ void bt_mesh_rx_reset(void)
|
||||
for (i = 0; i < ARRAY_SIZE(seg_rx); i++) {
|
||||
seg_rx_reset(&seg_rx[i], true);
|
||||
}
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
|
||||
bt_mesh_clear_rpl();
|
||||
} else {
|
||||
(void)memset(bt_mesh.rpl, 0, sizeof(bt_mesh.rpl));
|
||||
}
|
||||
}
|
||||
|
||||
void bt_mesh_tx_reset(void)
|
||||
|
||||
@@ -189,6 +189,10 @@ static enum net_verdict ieee802154_recv(struct net_if *iface,
|
||||
return NET_DROP;
|
||||
}
|
||||
|
||||
if (mpdu.mhr.fs->fc.frame_type == IEEE802154_FRAME_TYPE_ACK) {
|
||||
return NET_DROP;
|
||||
}
|
||||
|
||||
if (mpdu.mhr.fs->fc.frame_type == IEEE802154_FRAME_TYPE_BEACON) {
|
||||
return ieee802154_handle_beacon(iface, &mpdu,
|
||||
net_pkt_ieee802154_lqi(pkt));
|
||||
|
||||
@@ -215,6 +215,11 @@ void ieee802154_fragment(struct ieee802154_fragment_ctx *ctx,
|
||||
ctx->offset = ctx->processed >> 3;
|
||||
}
|
||||
|
||||
static inline uint8_t get_datagram_type(uint8_t *ptr)
|
||||
{
|
||||
return ptr[0] & NET_FRAG_DISPATCH_MASK;
|
||||
}
|
||||
|
||||
static inline uint16_t get_datagram_size(uint8_t *ptr)
|
||||
{
|
||||
return ((ptr[0] & 0x1F) << 8) | ptr[1];
|
||||
@@ -344,8 +349,7 @@ static inline struct frag_cache *get_reass_cache(uint16_t size, uint16_t tag)
|
||||
|
||||
static inline void fragment_append(struct net_pkt *pkt, struct net_buf *frag)
|
||||
{
|
||||
if ((frag->data[0] & NET_FRAG_DISPATCH_MASK) ==
|
||||
NET_6LO_DISPATCH_FRAG1) {
|
||||
if (get_datagram_type(frag->data) == NET_6LO_DISPATCH_FRAG1) {
|
||||
/* Always make sure first fragment is inserted first
|
||||
* This will be useful for fragment_cached_pkt_len()
|
||||
*/
|
||||
@@ -367,8 +371,7 @@ static inline size_t fragment_cached_pkt_len(struct net_pkt *pkt)
|
||||
while (frag) {
|
||||
uint16_t hdr_len = NET_6LO_FRAGN_HDR_LEN;
|
||||
|
||||
if ((frag->data[0] & NET_FRAG_DISPATCH_MASK) ==
|
||||
NET_6LO_DISPATCH_FRAG1) {
|
||||
if (get_datagram_type(frag->data) == NET_6LO_DISPATCH_FRAG1) {
|
||||
hdr_len = NET_6LO_FRAG1_HDR_LEN;
|
||||
}
|
||||
|
||||
@@ -396,8 +399,7 @@ static inline size_t fragment_cached_pkt_len(struct net_pkt *pkt)
|
||||
|
||||
static inline uint16_t fragment_offset(struct net_buf *frag)
|
||||
{
|
||||
if ((frag->data[0] & NET_FRAG_DISPATCH_MASK) ==
|
||||
NET_6LO_DISPATCH_FRAG1) {
|
||||
if (get_datagram_type(frag->data) == NET_6LO_DISPATCH_FRAG1) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -435,8 +437,7 @@ static inline void fragment_remove_headers(struct net_pkt *pkt)
|
||||
while (frag) {
|
||||
uint16_t hdr_len = NET_6LO_FRAGN_HDR_LEN;
|
||||
|
||||
if ((frag->data[0] & NET_FRAG_DISPATCH_MASK) ==
|
||||
NET_6LO_DISPATCH_FRAG1) {
|
||||
if (get_datagram_type(frag->data) == NET_6LO_DISPATCH_FRAG1) {
|
||||
hdr_len = NET_6LO_FRAG1_HDR_LEN;
|
||||
}
|
||||
|
||||
@@ -471,6 +472,11 @@ static inline void fragment_reconstruct_packet(struct net_pkt *pkt)
|
||||
fragment_remove_headers(pkt);
|
||||
}
|
||||
|
||||
static inline bool fragment_packet_valid(struct net_pkt *pkt)
|
||||
{
|
||||
return (get_datagram_type(pkt->buffer->data) == NET_6LO_DISPATCH_FRAG1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse size and tag from the fragment, check if we have any cache
|
||||
* related to it. If not create a new cache.
|
||||
@@ -486,18 +492,28 @@ static inline enum net_verdict fragment_add_to_cache(struct net_pkt *pkt)
|
||||
struct net_buf *frag;
|
||||
uint16_t size;
|
||||
uint16_t tag;
|
||||
uint8_t type;
|
||||
|
||||
frag = pkt->buffer;
|
||||
type = get_datagram_type(frag->data);
|
||||
|
||||
if ((type == NET_6LO_DISPATCH_FRAG1 &&
|
||||
frag->len < NET_6LO_FRAG1_HDR_LEN) ||
|
||||
(type == NET_6LO_DISPATCH_FRAGN &&
|
||||
frag->len < NET_6LO_FRAGN_HDR_LEN)) {
|
||||
return NET_DROP;
|
||||
}
|
||||
|
||||
/* Parse total size of packet */
|
||||
size = get_datagram_size(pkt->buffer->data);
|
||||
size = get_datagram_size(frag->data);
|
||||
|
||||
/* Parse the datagram tag */
|
||||
tag = get_datagram_tag(pkt->buffer->data +
|
||||
tag = get_datagram_tag(frag->data +
|
||||
NET_6LO_FRAG_DATAGRAM_SIZE_LEN);
|
||||
|
||||
/* If there are no fragments in the cache means this frag
|
||||
* is the first one. So cache Rx pkt otherwise not.
|
||||
*/
|
||||
frag = pkt->buffer;
|
||||
pkt->buffer = NULL;
|
||||
|
||||
cache = get_reass_cache(size, tag);
|
||||
@@ -515,15 +531,26 @@ static inline enum net_verdict fragment_add_to_cache(struct net_pkt *pkt)
|
||||
fragment_append(cache->pkt, frag);
|
||||
|
||||
if (fragment_cached_pkt_len(cache->pkt) == cache->size) {
|
||||
/* Assign buffer back to input packet. */
|
||||
pkt->buffer = cache->pkt->buffer;
|
||||
cache->pkt->buffer = NULL;
|
||||
if (!first_frag) {
|
||||
/* Assign buffer back to input packet. */
|
||||
pkt->buffer = cache->pkt->buffer;
|
||||
cache->pkt->buffer = NULL;
|
||||
} else {
|
||||
/* in case pkt == cache->pkt, we don't want
|
||||
* to unref it while clearing the cach.
|
||||
*/
|
||||
cache->pkt = NULL;
|
||||
}
|
||||
|
||||
clear_reass_cache(size, tag);
|
||||
|
||||
if (!fragment_packet_valid(pkt)) {
|
||||
NET_ERR("Invalid fragmented packet");
|
||||
return NET_DROP;
|
||||
}
|
||||
|
||||
fragment_reconstruct_packet(pkt);
|
||||
|
||||
/* Once reassemble is done, cache is no longer needed. */
|
||||
clear_reass_cache(size, tag);
|
||||
|
||||
if (!net_6lo_uncompress(pkt)) {
|
||||
NET_ERR("Could not uncompress. Bogus packet?");
|
||||
return NET_DROP;
|
||||
@@ -556,8 +583,7 @@ enum net_verdict ieee802154_reassemble(struct net_pkt *pkt)
|
||||
return NET_DROP;
|
||||
}
|
||||
|
||||
if ((pkt->buffer->data[0] & NET_FRAG_DISPATCH_MASK) >=
|
||||
NET_6LO_DISPATCH_FRAG1) {
|
||||
if (get_datagram_type(pkt->buffer->data) >= NET_6LO_DISPATCH_FRAG1) {
|
||||
return fragment_add_to_cache(pkt);
|
||||
} else {
|
||||
NET_DBG("No frag dispatch (%02x)", pkt->buffer->data[0]);
|
||||
|
||||
@@ -89,10 +89,10 @@ struct ieee802154_fcf_seq *ieee802154_validate_fc_seq(uint8_t *buf, uint8_t **p_
|
||||
return fs;
|
||||
}
|
||||
|
||||
static inline struct ieee802154_address_field *
|
||||
validate_addr(uint8_t *buf, uint8_t **p_buf, uint8_t *length,
|
||||
enum ieee802154_addressing_mode mode,
|
||||
bool pan_id_compression)
|
||||
static inline bool validate_addr(uint8_t *buf, uint8_t **p_buf, uint8_t *length,
|
||||
enum ieee802154_addressing_mode mode,
|
||||
bool pan_id_compression,
|
||||
struct ieee802154_address_field **addr)
|
||||
{
|
||||
uint8_t len = 0;
|
||||
|
||||
@@ -102,7 +102,8 @@ validate_addr(uint8_t *buf, uint8_t **p_buf, uint8_t *length,
|
||||
buf, mode, pan_id_compression);
|
||||
|
||||
if (mode == IEEE802154_ADDR_MODE_NONE) {
|
||||
return NULL;
|
||||
*addr = NULL;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!pan_id_compression) {
|
||||
@@ -117,13 +118,15 @@ validate_addr(uint8_t *buf, uint8_t **p_buf, uint8_t *length,
|
||||
}
|
||||
|
||||
if (len > *length) {
|
||||
return NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
*p_buf += len;
|
||||
*length -= len;
|
||||
|
||||
return (struct ieee802154_address_field *)buf;
|
||||
*addr = (struct ieee802154_address_field *)buf;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_NET_L2_IEEE802154_SECURITY
|
||||
@@ -439,13 +442,15 @@ bool ieee802154_validate_frame(uint8_t *buf, uint8_t length,
|
||||
return false;
|
||||
}
|
||||
|
||||
mpdu->mhr.dst_addr = validate_addr(p_buf, &p_buf, &length,
|
||||
mpdu->mhr.fs->fc.dst_addr_mode,
|
||||
false);
|
||||
|
||||
mpdu->mhr.src_addr = validate_addr(p_buf, &p_buf, &length,
|
||||
mpdu->mhr.fs->fc.src_addr_mode,
|
||||
(mpdu->mhr.fs->fc.pan_id_comp));
|
||||
if (!validate_addr(p_buf, &p_buf, &length,
|
||||
mpdu->mhr.fs->fc.dst_addr_mode,
|
||||
false, &mpdu->mhr.dst_addr) ||
|
||||
!validate_addr(p_buf, &p_buf, &length,
|
||||
mpdu->mhr.fs->fc.src_addr_mode,
|
||||
(mpdu->mhr.fs->fc.pan_id_comp),
|
||||
&mpdu->mhr.src_addr)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_NET_L2_IEEE802154_SECURITY
|
||||
if (mpdu->mhr.fs->fc.security_enabled) {
|
||||
|
||||
@@ -21,6 +21,7 @@ CONFIG_BT_DEVICE_NAME_DYNAMIC=y
|
||||
CONFIG_BT_L2CAP_TX_BUF_COUNT=4
|
||||
CONFIG_BT_ID_MAX=2
|
||||
CONFIG_BT_EATT=y
|
||||
CONFIG_BT_L2CAP_ECRED=y
|
||||
CONFIG_BT_GATT_DYNAMIC_DB=y
|
||||
CONFIG_BT_HRS=y
|
||||
CONFIG_BT_WHITELIST=y
|
||||
|
||||
Reference in New Issue
Block a user