xref: /nrf52832-nimble/packages/NimBLE-latest/nimble/host/src/ble_store_util.c (revision 042d53a763ad75cb1465103098bb88c245d95138)
1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one
3  * or more contributor license agreements.  See the NOTICE file
4  * distributed with this work for additional information
5  * regarding copyright ownership.  The ASF licenses this file
6  * to you under the Apache License, Version 2.0 (the
7  * "License"); you may not use this file except in compliance
8  * with the License.  You may obtain a copy of the License at
9  *
10  *  http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing,
13  * software distributed under the License is distributed on an
14  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15  * KIND, either express or implied.  See the License for the
16  * specific language governing permissions and limitations
17  * under the License.
18  */
19 
20 #include "host/ble_store.h"
21 #include "ble_hs_priv.h"
22 
23 struct ble_store_util_peer_set {
24     ble_addr_t *peer_id_addrs;
25     int num_peers;
26     int max_peers;
27     int status;
28 };
29 
30 static int
ble_store_util_iter_unique_peer(int obj_type,union ble_store_value * val,void * arg)31 ble_store_util_iter_unique_peer(int obj_type,
32                                 union ble_store_value *val,
33                                 void *arg)
34 {
35     struct ble_store_util_peer_set *set;
36     int i;
37 
38     BLE_HS_DBG_ASSERT(obj_type == BLE_STORE_OBJ_TYPE_OUR_SEC ||
39                       obj_type == BLE_STORE_OBJ_TYPE_PEER_SEC);
40 
41     set = arg;
42 
43     /* Do nothing if this peer is a duplicate. */
44     for (i = 0; i < set->num_peers; i++) {
45         if (ble_addr_cmp(set->peer_id_addrs + i, &val->sec.peer_addr) == 0) {
46             return 0;
47         }
48     }
49 
50     if (set->num_peers >= set->max_peers) {
51         /* Overflow; abort the iterate procedure. */
52         set->status = BLE_HS_ENOMEM;
53         return 1;
54     }
55 
56     set->peer_id_addrs[set->num_peers] = val->sec.peer_addr;
57     set->num_peers++;
58 
59     return 0;
60 }
61 
62 /**
63  * Retrieves the set of peer addresses for which a bond has been established.
64  *
65  * @param out_peer_id_addrs     On success, the set of bonded peer addresses
66  *                                  gets written here.
67  * @param out_num_peers         On success, the number of bonds gets written
68  *                                  here.
69  * @param max_peers             The capacity of the destination buffer.
70  *
71  * @return                      0 on success;
72  *                              BLE_HS_ENOMEM if the destination buffer is too
73  *                                  small;
74  *                              Other nonzero on error.
75  */
76 int
ble_store_util_bonded_peers(ble_addr_t * out_peer_id_addrs,int * out_num_peers,int max_peers)77 ble_store_util_bonded_peers(ble_addr_t *out_peer_id_addrs, int *out_num_peers,
78                             int max_peers)
79 {
80     struct ble_store_util_peer_set set = {
81         .peer_id_addrs = out_peer_id_addrs,
82         .num_peers = 0,
83         .max_peers = max_peers,
84         .status = 0,
85     };
86     int rc;
87 
88     rc = ble_store_iterate(BLE_STORE_OBJ_TYPE_OUR_SEC,
89                            ble_store_util_iter_unique_peer,
90                            &set);
91     if (rc != 0) {
92         return rc;
93     }
94     if (set.status != 0) {
95         return set.status;
96     }
97 
98     *out_num_peers = set.num_peers;
99     return 0;
100 }
101 
102 /**
103  * Deletes all entries from the store that are attached to the specified peer
104  * address.  This function deletes security entries and CCCD records.
105  *
106  * @param peer_id_addr          Entries with this peer address get deleted.
107  *
108  * @return                      0 on success;
109  *                              Other nonzero on error.
110  */
111 int
ble_store_util_delete_peer(const ble_addr_t * peer_id_addr)112 ble_store_util_delete_peer(const ble_addr_t *peer_id_addr)
113 {
114     union ble_store_key key;
115     int rc;
116 
117     memset(&key, 0, sizeof key);
118     key.sec.peer_addr = *peer_id_addr;
119 
120     rc = ble_store_util_delete_all(BLE_STORE_OBJ_TYPE_OUR_SEC, &key);
121     if (rc != 0) {
122         return rc;
123     }
124 
125     rc = ble_store_util_delete_all(BLE_STORE_OBJ_TYPE_PEER_SEC, &key);
126     if (rc != 0) {
127         return rc;
128     }
129 
130     memset(&key, 0, sizeof key);
131     key.cccd.peer_addr = *peer_id_addr;
132 
133     rc = ble_store_util_delete_all(BLE_STORE_OBJ_TYPE_CCCD, &key);
134     if (rc != 0) {
135         return rc;
136     }
137 
138     return 0;
139 }
140 
141 /**
142  * Deletes all entries from the store that match the specified key.
143  *
144  * @param type                  The type of store entry to delete.
145  * @param key                   Entries matching this key get deleted.
146  *
147  * @return                      0 on success;
148  *                              Other nonzero on error.
149  */
150 int
ble_store_util_delete_all(int type,const union ble_store_key * key)151 ble_store_util_delete_all(int type, const union ble_store_key *key)
152 {
153     int rc;
154 
155     do {
156         rc = ble_store_delete(type, key);
157     } while (rc == 0);
158 
159     if (rc != BLE_HS_ENOENT) {
160         return rc;
161     }
162 
163     return 0;
164 }
165 
166 static int
ble_store_util_iter_count(int obj_type,union ble_store_value * val,void * arg)167 ble_store_util_iter_count(int obj_type,
168                           union ble_store_value *val,
169                           void *arg)
170 {
171     int *count;
172 
173     count = arg;
174     (*count)++;
175 
176     return 0;
177 }
178 
179 int
ble_store_util_count(int type,int * out_count)180 ble_store_util_count(int type, int *out_count)
181 {
182     int rc;
183 
184     *out_count = 0;
185     rc = ble_store_iterate(type,
186                            ble_store_util_iter_count,
187                            out_count);
188     if (rc != 0) {
189         return rc;
190     }
191 
192     return 0;
193 }
194 
195 int
ble_store_util_delete_oldest_peer(void)196 ble_store_util_delete_oldest_peer(void)
197 {
198     ble_addr_t peer_id_addrs[MYNEWT_VAL(BLE_STORE_MAX_BONDS)];
199     int num_peers;
200     int rc;
201 
202     rc = ble_store_util_bonded_peers(
203             peer_id_addrs, &num_peers,
204             sizeof peer_id_addrs / sizeof peer_id_addrs[0]);
205     if (rc != 0) {
206         return rc;
207     }
208 
209     if (num_peers == 0) {
210         return 0;
211     }
212 
213     rc = ble_store_util_delete_peer(&peer_id_addrs[0]);
214     if (rc != 0) {
215         return rc;
216     }
217 
218     return 0;
219 }
220 
221 /**
222  * Round-robin status callback.  If a there is insufficient storage capacity
223  * for a new record, delete the oldest bond and proceed with the persist
224  * operation.
225  *
226  * Note: This is not the best behavior for an actual product because
227  * uninteresting peers could cause important bonds to be deleted.  This is
228  * useful for demonstrations and sample apps.
229  */
230 int
ble_store_util_status_rr(struct ble_store_status_event * event,void * arg)231 ble_store_util_status_rr(struct ble_store_status_event *event, void *arg)
232 {
233     switch (event->event_code) {
234     case BLE_STORE_EVENT_OVERFLOW:
235         switch (event->overflow.obj_type) {
236             case BLE_STORE_OBJ_TYPE_OUR_SEC:
237             case BLE_STORE_OBJ_TYPE_PEER_SEC:
238             case BLE_STORE_OBJ_TYPE_CCCD:
239                 return ble_gap_unpair_oldest_peer();
240 
241             default:
242                 return BLE_HS_EUNKNOWN;
243         }
244 
245     case BLE_STORE_EVENT_FULL:
246         /* Just proceed with the operation.  If it results in an overflow,
247          * we'll delete a record when the overflow occurs.
248          */
249         return 0;
250 
251     default:
252         return BLE_HS_EUNKNOWN;
253     }
254 }
255