mirror of
https://github.com/espressif/esp-nimble.git
synced 2026-09-28 19:57:23 +00:00
This API allows to unpair a device with the specified address. The keys related to that peer device are removed from storage and peer address is removed from the resolve list from the controller. If a peer is connected, the connection is terminated. This function is used in policy for SM key overflow. Instead of just deleting the keys from storage, the host performs tasks described above to ensure correct behavior.
255 lines
6.5 KiB
C
255 lines
6.5 KiB
C
/*
|
|
* Licensed to the Apache Software Foundation (ASF) under one
|
|
* or more contributor license agreements. See the NOTICE file
|
|
* distributed with this work for additional information
|
|
* regarding copyright ownership. The ASF licenses this file
|
|
* to you under the Apache License, Version 2.0 (the
|
|
* "License"); you may not use this file except in compliance
|
|
* with the License. You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing,
|
|
* software distributed under the License is distributed on an
|
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
* KIND, either express or implied. See the License for the
|
|
* specific language governing permissions and limitations
|
|
* under the License.
|
|
*/
|
|
|
|
#include "host/ble_store.h"
|
|
#include "ble_hs_priv.h"
|
|
|
|
struct ble_store_util_peer_set {
|
|
ble_addr_t *peer_id_addrs;
|
|
int num_peers;
|
|
int max_peers;
|
|
int status;
|
|
};
|
|
|
|
static int
|
|
ble_store_util_iter_unique_peer(int obj_type,
|
|
union ble_store_value *val,
|
|
void *arg)
|
|
{
|
|
struct ble_store_util_peer_set *set;
|
|
int i;
|
|
|
|
BLE_HS_DBG_ASSERT(obj_type == BLE_STORE_OBJ_TYPE_OUR_SEC ||
|
|
obj_type == BLE_STORE_OBJ_TYPE_PEER_SEC);
|
|
|
|
set = arg;
|
|
|
|
/* Do nothing if this peer is a duplicate. */
|
|
for (i = 0; i < set->num_peers; i++) {
|
|
if (ble_addr_cmp(set->peer_id_addrs + i, &val->sec.peer_addr) == 0) {
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
if (set->num_peers >= set->max_peers) {
|
|
/* Overflow; abort the iterate procedure. */
|
|
set->status = BLE_HS_ENOMEM;
|
|
return 1;
|
|
}
|
|
|
|
set->peer_id_addrs[set->num_peers] = val->sec.peer_addr;
|
|
set->num_peers++;
|
|
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* Retrieves the set of peer addresses for which a bond has been established.
|
|
*
|
|
* @param out_peer_id_addrs On success, the set of bonded peer addresses
|
|
* gets written here.
|
|
* @param out_num_peers On success, the number of bonds gets written
|
|
* here.
|
|
* @param max_peers The capacity of the destination buffer.
|
|
*
|
|
* @return 0 on success;
|
|
* BLE_HS_ENOMEM if the destination buffer is too
|
|
* small;
|
|
* Other nonzero on error.
|
|
*/
|
|
int
|
|
ble_store_util_bonded_peers(ble_addr_t *out_peer_id_addrs, int *out_num_peers,
|
|
int max_peers)
|
|
{
|
|
struct ble_store_util_peer_set set = {
|
|
.peer_id_addrs = out_peer_id_addrs,
|
|
.num_peers = 0,
|
|
.max_peers = max_peers,
|
|
.status = 0,
|
|
};
|
|
int rc;
|
|
|
|
rc = ble_store_iterate(BLE_STORE_OBJ_TYPE_OUR_SEC,
|
|
ble_store_util_iter_unique_peer,
|
|
&set);
|
|
if (rc != 0) {
|
|
return rc;
|
|
}
|
|
if (set.status != 0) {
|
|
return set.status;
|
|
}
|
|
|
|
*out_num_peers = set.num_peers;
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* Deletes all entries from the store that are attached to the specified peer
|
|
* address. This function deletes security entries and CCCD records.
|
|
*
|
|
* @param peer_id_addr Entries with this peer address get deleted.
|
|
*
|
|
* @return 0 on success;
|
|
* Other nonzero on error.
|
|
*/
|
|
int
|
|
ble_store_util_delete_peer(const ble_addr_t *peer_id_addr)
|
|
{
|
|
union ble_store_key key;
|
|
int rc;
|
|
|
|
memset(&key, 0, sizeof key);
|
|
key.sec.peer_addr = *peer_id_addr;
|
|
|
|
rc = ble_store_util_delete_all(BLE_STORE_OBJ_TYPE_OUR_SEC, &key);
|
|
if (rc != 0) {
|
|
return rc;
|
|
}
|
|
|
|
rc = ble_store_util_delete_all(BLE_STORE_OBJ_TYPE_PEER_SEC, &key);
|
|
if (rc != 0) {
|
|
return rc;
|
|
}
|
|
|
|
memset(&key, 0, sizeof key);
|
|
key.cccd.peer_addr = *peer_id_addr;
|
|
|
|
rc = ble_store_util_delete_all(BLE_STORE_OBJ_TYPE_CCCD, &key);
|
|
if (rc != 0) {
|
|
return rc;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* Deletes all entries from the store that match the specified key.
|
|
*
|
|
* @param type The type of store entry to delete.
|
|
* @param key Entries matching this key get deleted.
|
|
*
|
|
* @return 0 on success;
|
|
* Other nonzero on error.
|
|
*/
|
|
int
|
|
ble_store_util_delete_all(int type, const union ble_store_key *key)
|
|
{
|
|
int rc;
|
|
|
|
do {
|
|
rc = ble_store_delete(type, key);
|
|
} while (rc == 0);
|
|
|
|
if (rc != BLE_HS_ENOENT) {
|
|
return rc;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int
|
|
ble_store_util_iter_count(int obj_type,
|
|
union ble_store_value *val,
|
|
void *arg)
|
|
{
|
|
int *count;
|
|
|
|
count = arg;
|
|
(*count)++;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
ble_store_util_count(int type, int *out_count)
|
|
{
|
|
int rc;
|
|
|
|
*out_count = 0;
|
|
rc = ble_store_iterate(type,
|
|
ble_store_util_iter_count,
|
|
out_count);
|
|
if (rc != 0) {
|
|
return rc;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
ble_store_util_delete_oldest_peer(void)
|
|
{
|
|
ble_addr_t peer_id_addrs[MYNEWT_VAL(BLE_STORE_MAX_BONDS)];
|
|
int num_peers;
|
|
int rc;
|
|
|
|
rc = ble_store_util_bonded_peers(
|
|
peer_id_addrs, &num_peers,
|
|
sizeof peer_id_addrs / sizeof peer_id_addrs[0]);
|
|
if (rc != 0) {
|
|
return rc;
|
|
}
|
|
|
|
if (num_peers == 0) {
|
|
return 0;
|
|
}
|
|
|
|
rc = ble_store_util_delete_peer(&peer_id_addrs[0]);
|
|
if (rc != 0) {
|
|
return rc;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* Round-robin status callback. If a there is insufficient storage capacity
|
|
* for a new record, delete the oldest bond and proceed with the persist
|
|
* operation.
|
|
*
|
|
* Note: This is not the best behavior for an actual product because
|
|
* uninteresting peers could cause important bonds to be deleted. This is
|
|
* useful for demonstrations and sample apps.
|
|
*/
|
|
int
|
|
ble_store_util_status_rr(struct ble_store_status_event *event, void *arg)
|
|
{
|
|
switch (event->event_code) {
|
|
case BLE_STORE_EVENT_OVERFLOW:
|
|
switch (event->overflow.obj_type) {
|
|
case BLE_STORE_OBJ_TYPE_OUR_SEC:
|
|
case BLE_STORE_OBJ_TYPE_PEER_SEC:
|
|
case BLE_STORE_OBJ_TYPE_CCCD:
|
|
return ble_gap_unpair_oldest_peer();
|
|
|
|
default:
|
|
return BLE_HS_EUNKNOWN;
|
|
}
|
|
|
|
case BLE_STORE_EVENT_FULL:
|
|
/* Just proceed with the operation. If it results in an overflow,
|
|
* we'll delete a record when the overflow occurs.
|
|
*/
|
|
return 0;
|
|
|
|
default:
|
|
return BLE_HS_EUNKNOWN;
|
|
}
|
|
}
|