diff --git a/nimble/host/include/host/ble_store.h b/nimble/host/include/host/ble_store.h index 6257b3810..ec39ea823 100644 --- a/nimble/host/include/host/ble_store.h +++ b/nimble/host/include/host/ble_store.h @@ -205,6 +205,10 @@ void ble_store_key_from_value_sec(struct ble_store_key_sec *out_key, void ble_store_key_from_value_cccd(struct ble_store_key_cccd *out_key, struct ble_store_value_cccd *value); +void ble_store_key_from_value(int obj_type, + union ble_store_key *out_key, + union ble_store_value *value); + typedef int ble_store_iterator_fn(int obj_type, union ble_store_value *val, void *cookie); @@ -213,6 +217,14 @@ int ble_store_iterate(int obj_type, ble_store_iterator_fn *callback, void *cookie); +/*** Utility functions. */ + +int ble_store_util_bonded_peers(ble_addr_t *out_peer_id_addrs, + int *out_num_peers, + int max_peers); +int ble_store_util_delete_all(int type, const union ble_store_key *key); +int ble_store_util_delete_peer(const ble_addr_t *peer_id_addr); + #ifdef __cplusplus } #endif diff --git a/nimble/host/src/ble_store.c b/nimble/host/src/ble_store.c index 2146427f9..88697ac50 100644 --- a/nimble/host/src/ble_store.c +++ b/nimble/host/src/ble_store.c @@ -236,6 +236,27 @@ ble_store_key_from_value_sec(struct ble_store_key_sec *out_key, out_key->idx = 0; } +void +ble_store_key_from_value(int obj_type, + union ble_store_key *out_key, + union ble_store_value *value) +{ + switch (obj_type) { + case BLE_STORE_OBJ_TYPE_OUR_SEC: + case BLE_STORE_OBJ_TYPE_PEER_SEC: + ble_store_key_from_value_sec(&out_key->sec, &value->sec); + break; + + case BLE_STORE_OBJ_TYPE_CCCD: + ble_store_key_from_value_cccd(&out_key->cccd, &value->cccd); + break; + + default: + BLE_HS_DBG_ASSERT(0); + break; + } +} + int ble_store_iterate(int obj_type, ble_store_iterator_fn *callback, @@ -258,6 +279,7 @@ ble_store_iterate(int obj_type, case BLE_STORE_OBJ_TYPE_CCCD: key.cccd.peer_addr = *BLE_ADDR_ANY; pidx = &key.cccd.idx; + break; default: BLE_HS_DBG_ASSERT(0); return BLE_HS_EINVAL; diff --git a/nimble/host/src/ble_store_util.c b/nimble/host/src/ble_store_util.c new file mode 100644 index 000000000..2025222a7 --- /dev/null +++ b/nimble/host/src/ble_store_util.c @@ -0,0 +1,164 @@ +/* + * 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; +}