system/bt
修訂 | 013c32bf98b8d511dc29fcd7de7578a421a52590 (tree) |
---|---|
時間 | 2016-09-28 16:05:16 |
作者 | Andre Eisenbach <eisenbach@goog...> |
Commiter | Andre Eisenbach |
Fix 100 LE device connection limitation
Currently after 100 devices are added to the device security database,
any subsequent LE connection to a newly discovered LE device address
will fail as entries in the security record database are not reused.
This patch removes a device record if the device itself is removed and
also ensures that the oldest device security record is deleted if the
limit is reached to ensure a new record can be allocated.
Bug: 31625900
Change-Id: I22f6c82c64a9a9bfb2a16d79182903e5aa011355
@@ -50,6 +50,7 @@ extern void smp_link_encrypted(BD_ADDR bda, UINT8 encr_enable); | ||
50 | 50 | extern BOOLEAN smp_proc_ltk_request(BD_ADDR bda); |
51 | 51 | #endif |
52 | 52 | extern void gatt_notify_enc_cmpl(BD_ADDR bd_addr); |
53 | + | |
53 | 54 | /*******************************************************************************/ |
54 | 55 | /* External Function to be called by other modules */ |
55 | 56 | /*******************************************************************************/ |
@@ -73,16 +74,11 @@ BOOLEAN BTM_SecAddBleDevice (BD_ADDR bd_addr, BD_NAME bd_name, tBT_DEVICE_TYPE d | ||
73 | 74 | tBLE_ADDR_TYPE addr_type) |
74 | 75 | { |
75 | 76 | BTM_TRACE_DEBUG ("%s: dev_type=0x%x", __func__, dev_type); |
76 | - tBTM_SEC_DEV_REC *p_dev_rec = btm_find_dev(bd_addr); | |
77 | - | |
78 | - if (!p_dev_rec) { | |
79 | - if (list_length(btm_cb.sec_dev_rec) > BTM_SEC_MAX_DEVICE_RECORDS) { | |
80 | - BTM_TRACE_ERROR("%s: %d max devices reached!", __func__, BTM_SEC_MAX_DEVICE_RECORDS); | |
81 | - return FALSE; | |
82 | - } | |
83 | 77 | |
84 | - p_dev_rec = osi_calloc(sizeof(tBTM_SEC_DEV_REC)); | |
85 | - list_append(btm_cb.sec_dev_rec, p_dev_rec); | |
78 | + tBTM_SEC_DEV_REC *p_dev_rec = btm_find_dev(bd_addr); | |
79 | + if (!p_dev_rec) | |
80 | + { | |
81 | + p_dev_rec = btm_sec_allocate_dev_rec(); | |
86 | 82 | |
87 | 83 | memcpy(p_dev_rec->bd_addr, bd_addr, BD_ADDR_LEN); |
88 | 84 | p_dev_rec->hci_handle = BTM_GetHCIConnHandle(bd_addr, BT_TRANSPORT_BR_EDR); |
@@ -37,8 +37,6 @@ | ||
37 | 37 | #include "hcidefs.h" |
38 | 38 | #include "l2c_api.h" |
39 | 39 | |
40 | -static tBTM_SEC_DEV_REC *btm_find_oldest_dev (void); | |
41 | - | |
42 | 40 | /******************************************************************************* |
43 | 41 | ** |
44 | 42 | ** Function BTM_SecAddDevice |
@@ -63,22 +61,12 @@ BOOLEAN BTM_SecAddDevice (BD_ADDR bd_addr, DEV_CLASS dev_class, BD_NAME bd_name, | ||
63 | 61 | LINK_KEY link_key, UINT8 key_type, tBTM_IO_CAP io_cap, |
64 | 62 | UINT8 pin_length) |
65 | 63 | { |
66 | - tBTM_SEC_DEV_REC *p_dev_rec; | |
67 | - int i, j; | |
68 | - BOOLEAN found = FALSE; | |
69 | - | |
70 | 64 | BTM_TRACE_API("%s: link key type:%x", __func__, key_type); |
71 | - p_dev_rec = btm_find_dev (bd_addr); | |
65 | + | |
66 | + tBTM_SEC_DEV_REC *p_dev_rec = btm_find_dev (bd_addr); | |
72 | 67 | if (!p_dev_rec) |
73 | 68 | { |
74 | - if (list_length(btm_cb.sec_dev_rec) > BTM_SEC_MAX_DEVICE_RECORDS) { | |
75 | - BTM_TRACE_DEBUG("%s: Max devices reached!", __func__); | |
76 | - return FALSE; | |
77 | - } | |
78 | - | |
79 | - BTM_TRACE_DEBUG ("%s: allocate a new dev rec", __func__); | |
80 | - p_dev_rec = osi_calloc(sizeof(tBTM_SEC_DEV_REC)); | |
81 | - list_append(btm_cb.sec_dev_rec, p_dev_rec); | |
69 | + p_dev_rec = btm_sec_allocate_dev_rec(); | |
82 | 70 | |
83 | 71 | memcpy (p_dev_rec->bd_addr, bd_addr, BD_ADDR_LEN); |
84 | 72 | p_dev_rec->hci_handle = BTM_GetHCIConnHandle (bd_addr, BT_TRANSPORT_BR_EDR); |
@@ -88,11 +76,19 @@ BOOLEAN BTM_SecAddDevice (BD_ADDR bd_addr, DEV_CLASS dev_class, BD_NAME bd_name, | ||
88 | 76 | /* update conn params, use default value for background connection params */ |
89 | 77 | memset(&p_dev_rec->conn_params, 0xff, sizeof(tBTM_LE_CONN_PRAMS)); |
90 | 78 | #endif |
79 | + } else { | |
80 | + /* "Bump" timestamp for existing record */ | |
81 | + p_dev_rec->timestamp = btm_cb.dev_rec_count++; | |
82 | + | |
83 | + /* TODO(eisenbach): | |
84 | + * Small refactor, but leaving original logic for now. | |
85 | + * On the surface, this does not make any sense at all. Why change the | |
86 | + * bond state for an existing device here? This logic should be verified | |
87 | + * as part of a larger refactor. | |
88 | + */ | |
89 | + p_dev_rec->bond_type = BOND_TYPE_UNKNOWN; | |
91 | 90 | } |
92 | 91 | |
93 | - p_dev_rec->bond_type = BOND_TYPE_UNKNOWN; /* Default value */ | |
94 | - p_dev_rec->timestamp = btm_cb.dev_rec_count++; | |
95 | - | |
96 | 92 | if (dev_class) |
97 | 93 | memcpy (p_dev_rec->dev_class, dev_class, DEV_CLASS_LEN); |
98 | 94 |
@@ -108,26 +104,23 @@ BOOLEAN BTM_SecAddDevice (BD_ADDR bd_addr, DEV_CLASS dev_class, BD_NAME bd_name, | ||
108 | 104 | p_dev_rec->num_read_pages = 0; |
109 | 105 | if (features) |
110 | 106 | { |
107 | + BOOLEAN found = FALSE; | |
111 | 108 | memcpy (p_dev_rec->features, features, sizeof (p_dev_rec->features)); |
112 | - for (i = HCI_EXT_FEATURES_PAGE_MAX; i >= 0; i--) | |
109 | + for (int i = HCI_EXT_FEATURES_PAGE_MAX; !found && i >= 0; i--) | |
113 | 110 | { |
114 | - for (j = 0; j < HCI_FEATURE_BYTES_PER_PAGE; j++) | |
111 | + for (int j = 0; j < HCI_FEATURE_BYTES_PER_PAGE; j++) | |
115 | 112 | { |
116 | 113 | if (p_dev_rec->features[i][j] != 0) |
117 | 114 | { |
118 | 115 | found = TRUE; |
116 | + p_dev_rec->num_read_pages = i + 1; | |
119 | 117 | break; |
120 | 118 | } |
121 | 119 | } |
122 | - if (found) | |
123 | - { | |
124 | - p_dev_rec->num_read_pages = i + 1; | |
125 | - break; | |
126 | - } | |
127 | 120 | } |
128 | - } | |
129 | - else | |
121 | + } else { | |
130 | 122 | memset (p_dev_rec->features, 0, sizeof (p_dev_rec->features)); |
123 | + } | |
131 | 124 | |
132 | 125 | BTM_SEC_COPY_TRUSTED_DEVICE(trusted_mask, p_dev_rec->trusted_mask); |
133 | 126 |
@@ -177,8 +170,6 @@ BOOLEAN BTM_SecAddDevice (BD_ADDR bd_addr, DEV_CLASS dev_class, BD_NAME bd_name, | ||
177 | 170 | *******************************************************************************/ |
178 | 171 | BOOLEAN BTM_SecDeleteDevice (BD_ADDR bd_addr) |
179 | 172 | { |
180 | - tBTM_SEC_DEV_REC *p_dev_rec; | |
181 | - | |
182 | 173 | if (BTM_IsAclConnectionUp(bd_addr, BT_TRANSPORT_LE) || |
183 | 174 | BTM_IsAclConnectionUp(bd_addr, BT_TRANSPORT_BR_EDR)) |
184 | 175 | { |
@@ -186,7 +177,8 @@ BOOLEAN BTM_SecDeleteDevice (BD_ADDR bd_addr) | ||
186 | 177 | return FALSE; |
187 | 178 | } |
188 | 179 | |
189 | - if ((p_dev_rec = btm_find_dev(bd_addr)) != NULL) | |
180 | + tBTM_SEC_DEV_REC *p_dev_rec = btm_find_dev(bd_addr); | |
181 | + if (p_dev_rec != NULL) | |
190 | 182 | { |
191 | 183 | btm_sec_free_dev(p_dev_rec); |
192 | 184 | /* Tell controller to get rid of the link key, if it has one stored */ |
@@ -240,20 +232,10 @@ bool is_bd_addr_equal(void *data, void *context) | ||
240 | 232 | *******************************************************************************/ |
241 | 233 | tBTM_SEC_DEV_REC *btm_sec_alloc_dev (BD_ADDR bd_addr) |
242 | 234 | { |
243 | - tBTM_SEC_DEV_REC *p_dev_rec = NULL; | |
244 | 235 | tBTM_INQ_INFO *p_inq_info; |
245 | 236 | BTM_TRACE_EVENT ("btm_sec_alloc_dev"); |
246 | 237 | |
247 | - if (list_length(btm_cb.sec_dev_rec) > BTM_SEC_MAX_DEVICE_RECORDS) { | |
248 | - p_dev_rec = btm_find_oldest_dev(); | |
249 | - } else { | |
250 | - BTM_TRACE_DEBUG ("allocate a new dev rec"); | |
251 | - p_dev_rec = osi_calloc(sizeof(tBTM_SEC_DEV_REC)); | |
252 | - list_append(btm_cb.sec_dev_rec, p_dev_rec); | |
253 | - } | |
254 | - | |
255 | - p_dev_rec->bond_type = BOND_TYPE_UNKNOWN; /* Default value */ | |
256 | - p_dev_rec->sec_flags = BTM_SEC_IN_USE; | |
238 | + tBTM_SEC_DEV_REC *p_dev_rec = btm_sec_allocate_dev_rec(); | |
257 | 239 | |
258 | 240 | /* Check with the BT manager if details about remote device are known */ |
259 | 241 | /* outgoing connection */ |
@@ -280,7 +262,6 @@ tBTM_SEC_DEV_REC *btm_sec_alloc_dev (BD_ADDR bd_addr) | ||
280 | 262 | p_dev_rec->ble_hci_handle = BTM_GetHCIConnHandle (bd_addr, BT_TRANSPORT_LE); |
281 | 263 | #endif |
282 | 264 | p_dev_rec->hci_handle = BTM_GetHCIConnHandle (bd_addr, BT_TRANSPORT_BR_EDR); |
283 | - p_dev_rec->timestamp = btm_cb.dev_rec_count++; | |
284 | 265 | |
285 | 266 | return(p_dev_rec); |
286 | 267 | } |
@@ -295,17 +276,11 @@ tBTM_SEC_DEV_REC *btm_sec_alloc_dev (BD_ADDR bd_addr) | ||
295 | 276 | *******************************************************************************/ |
296 | 277 | void btm_sec_free_dev (tBTM_SEC_DEV_REC *p_dev_rec) |
297 | 278 | { |
298 | - p_dev_rec->bond_type = BOND_TYPE_UNKNOWN; | |
299 | - p_dev_rec->sec_flags = 0; | |
300 | - | |
301 | 279 | #if BLE_INCLUDED == TRUE |
302 | 280 | /* Clear out any saved BLE keys */ |
303 | 281 | btm_sec_clear_ble_keys (p_dev_rec); |
304 | - /* clear the ble block */ | |
305 | - memset(&p_dev_rec->ble, 0, sizeof(tBTM_SEC_BLE)); | |
306 | 282 | #endif |
307 | - | |
308 | - | |
283 | + list_remove(btm_cb.sec_dev_rec, p_dev_rec); | |
309 | 284 | } |
310 | 285 | |
311 | 286 | /******************************************************************************* |
@@ -475,8 +450,6 @@ void btm_consolidate_dev(tBTM_SEC_DEV_REC *p_target_rec) | ||
475 | 450 | |
476 | 451 | /* remove the combined record */ |
477 | 452 | list_remove(btm_cb.sec_dev_rec, p_dev_rec); |
478 | - | |
479 | - p_dev_rec->bond_type = BOND_TYPE_UNKNOWN; | |
480 | 453 | break; |
481 | 454 | } |
482 | 455 |
@@ -490,8 +463,6 @@ void btm_consolidate_dev(tBTM_SEC_DEV_REC *p_target_rec) | ||
490 | 463 | |
491 | 464 | /* remove the combined record */ |
492 | 465 | list_remove(btm_cb.sec_dev_rec, p_dev_rec); |
493 | - | |
494 | - p_dev_rec->bond_type = BOND_TYPE_UNKNOWN; | |
495 | 466 | } |
496 | 467 | break; |
497 | 468 | } |
@@ -524,48 +495,79 @@ tBTM_SEC_DEV_REC *btm_find_or_alloc_dev (BD_ADDR bd_addr) | ||
524 | 495 | |
525 | 496 | /******************************************************************************* |
526 | 497 | ** |
527 | -** Function btm_find_oldest_dev | |
498 | +** Function btm_find_oldest_dev_rec | |
528 | 499 | ** |
529 | 500 | ** Description Locates the oldest device in use. It first looks for |
530 | 501 | ** the oldest non-paired device. If all devices are paired it |
531 | -** deletes the oldest paired device. | |
502 | +** returns the oldest paired device. | |
532 | 503 | ** |
533 | 504 | ** Returns Pointer to the record or NULL |
534 | 505 | ** |
535 | 506 | *******************************************************************************/ |
536 | -tBTM_SEC_DEV_REC *btm_find_oldest_dev (void) | |
507 | +static tBTM_SEC_DEV_REC* btm_find_oldest_dev_rec (void) | |
537 | 508 | { |
538 | 509 | tBTM_SEC_DEV_REC *p_oldest = NULL; |
539 | - UINT32 ot = 0xFFFFFFFF; | |
510 | + UINT32 ts_oldest = 0xFFFFFFFF; | |
540 | 511 | tBTM_SEC_DEV_REC *p_oldest_paired = NULL; |
541 | - UINT32 ot_paired = 0xFFFFFFFF; | |
512 | + UINT32 ts_oldest_paired = 0xFFFFFFFF; | |
542 | 513 | |
543 | - /* First look for the non-paired devices for the oldest entry */ | |
544 | 514 | list_node_t *end = list_end(btm_cb.sec_dev_rec); |
545 | 515 | for (list_node_t *node = list_begin(btm_cb.sec_dev_rec); node != end; node = list_next(node)) { |
546 | 516 | tBTM_SEC_DEV_REC *p_dev_rec = list_node(node); |
547 | - /* Device is not paired */ | |
548 | - if ((p_dev_rec->sec_flags & (BTM_SEC_LINK_KEY_KNOWN |BTM_SEC_LE_LINK_KEY_KNOWN)) == 0) { | |
549 | - if (p_dev_rec->timestamp < ot) { | |
517 | + | |
518 | + if ((p_dev_rec->sec_flags & (BTM_SEC_LINK_KEY_KNOWN | BTM_SEC_LE_LINK_KEY_KNOWN)) == 0) { | |
519 | + // Device is not paired | |
520 | + if (p_dev_rec->timestamp < ts_oldest) { | |
550 | 521 | p_oldest = p_dev_rec; |
551 | - ot = p_dev_rec->timestamp; | |
522 | + ts_oldest = p_dev_rec->timestamp; | |
523 | + } | |
524 | + } else { | |
525 | + // Paired device | |
526 | + if (p_dev_rec->timestamp < ts_oldest_paired) { | |
527 | + p_oldest_paired = p_dev_rec; | |
528 | + ts_oldest_paired = p_dev_rec->timestamp; | |
552 | 529 | } |
553 | - continue; | |
554 | 530 | } |
531 | + } | |
555 | 532 | |
556 | - if (p_dev_rec->timestamp < ot_paired) { | |
557 | - p_oldest_paired = p_dev_rec; | |
558 | - ot_paired = p_dev_rec->timestamp; | |
559 | - } | |
533 | + // If we did not find any non-paired devices, use the oldest paired one... | |
534 | + if (ts_oldest == 0xFFFFFFFF) | |
535 | + p_oldest = p_oldest_paired; | |
536 | + | |
537 | + return p_oldest; | |
538 | +} | |
539 | + | |
540 | +/******************************************************************************* | |
541 | +** | |
542 | +** Function btm_sec_allocate_dev_rec | |
543 | +** | |
544 | +** Description Attempts to allocate a new device record. If we have | |
545 | +** exceeded the maximum number of allowable records to | |
546 | +** allocate, the oldest record will be deleted to make room | |
547 | +** for the new record. | |
548 | +** | |
549 | +** Returns Pointer to the newly allocated record | |
550 | +** | |
551 | +*******************************************************************************/ | |
552 | +tBTM_SEC_DEV_REC* btm_sec_allocate_dev_rec(void) | |
553 | +{ | |
554 | + tBTM_SEC_DEV_REC *p_dev_rec = NULL; | |
560 | 555 | |
556 | + if (list_length(btm_cb.sec_dev_rec) > BTM_SEC_MAX_DEVICE_RECORDS) | |
557 | + { | |
558 | + p_dev_rec = btm_find_oldest_dev_rec(); | |
559 | + list_remove(btm_cb.sec_dev_rec, p_dev_rec); | |
561 | 560 | } |
562 | 561 | |
563 | - /* if non-paired device return oldest */ | |
564 | - if (ot != 0xFFFFFFFF) | |
565 | - return(p_oldest); | |
562 | + p_dev_rec = osi_calloc(sizeof(tBTM_SEC_DEV_REC)); | |
563 | + list_append(btm_cb.sec_dev_rec, p_dev_rec); | |
564 | + | |
565 | + // Initialize defaults | |
566 | + p_dev_rec->sec_flags = BTM_SEC_IN_USE; | |
567 | + p_dev_rec->bond_type = BOND_TYPE_UNKNOWN; | |
568 | + p_dev_rec->timestamp = btm_cb.dev_rec_count++; | |
566 | 569 | |
567 | - /* only paired devices present, return oldest */ | |
568 | - return p_oldest_paired; | |
570 | + return p_dev_rec; | |
569 | 571 | } |
570 | 572 | |
571 | 573 | /******************************************************************************* |
@@ -1057,6 +1057,7 @@ extern void btm_report_device_status (tBTM_DEV_STATUS status); | ||
1057 | 1057 | */ |
1058 | 1058 | extern BOOLEAN btm_dev_support_switch (BD_ADDR bd_addr); |
1059 | 1059 | |
1060 | +extern tBTM_SEC_DEV_REC *btm_sec_allocate_dev_rec(void); | |
1060 | 1061 | extern tBTM_SEC_DEV_REC *btm_sec_alloc_dev (BD_ADDR bd_addr); |
1061 | 1062 | extern void btm_sec_free_dev (tBTM_SEC_DEV_REC *p_dev_rec); |
1062 | 1063 | extern tBTM_SEC_DEV_REC *btm_find_dev (BD_ADDR bd_addr); |