1 /****************************************************************************** 2 * 3 * Copyright (C) 2014 Google, Inc. 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at: 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 * 17 ******************************************************************************/ 18 19 #define LOG_TAG "bt_hci_packet_fragmenter" 20 21 #include "packet_fragmenter.h" 22 23 #include <assert.h> 24 #include <string.h> 25 26 #include "bt_target.h" 27 #include "buffer_allocator.h" 28 #include "device/include/controller.h" 29 #include "hci_internals.h" 30 #include "osi/include/hash_functions.h" 31 #include "osi/include/hash_map.h" 32 #include "osi/include/log.h" 33 #include "osi/include/osi.h" 34 35 #define APPLY_CONTINUATION_FLAG(handle) (((handle) & 0xCFFF) | 0x1000) 36 #define APPLY_START_FLAG(handle) (((handle) & 0xCFFF) | 0x2000) 37 #define SUB_EVENT(event) ((event) & MSG_SUB_EVT_MASK) 38 #define GET_BOUNDARY_FLAG(handle) (((handle) >> 12) & 0x0003) 39 40 #define HANDLE_MASK 0x0FFF 41 #define START_PACKET_BOUNDARY 2 42 #define CONTINUATION_PACKET_BOUNDARY 1 43 #define L2CAP_HEADER_SIZE 4 44 45 // TODO(zachoverflow): find good value for this 46 #define NUMBER_OF_BUCKETS 42 47 48 // Our interface and callbacks 49 static const packet_fragmenter_t interface; 50 static const allocator_t *buffer_allocator; 51 static const controller_t *controller; 52 static const packet_fragmenter_callbacks_t *callbacks; 53 54 static hash_map_t *partial_packets; 55 56 static void init(const packet_fragmenter_callbacks_t *result_callbacks) { 57 callbacks = result_callbacks; 58 partial_packets = hash_map_new(NUMBER_OF_BUCKETS, hash_function_naive, NULL, NULL, NULL); 59 } 60 61 static void cleanup() { 62 if (partial_packets) 63 hash_map_free(partial_packets); 64 } 65 66 static void fragment_and_dispatch(BT_HDR *packet) { 67 assert(packet != NULL); 68 69 uint16_t event = packet->event & MSG_EVT_MASK; 70 uint8_t *stream = packet->data + packet->offset; 71 72 // We only fragment ACL packets 73 if (event != MSG_STACK_TO_HC_HCI_ACL) { 74 callbacks->fragmented(packet, true); 75 return; 76 } 77 78 uint16_t max_data_size = 79 SUB_EVENT(packet->event) == LOCAL_BR_EDR_CONTROLLER_ID ? 80 controller->get_acl_data_size_classic() : 81 controller->get_acl_data_size_ble(); 82 83 uint16_t max_packet_size = max_data_size + HCI_ACL_PREAMBLE_SIZE; 84 uint16_t remaining_length = packet->len; 85 86 uint16_t continuation_handle; 87 STREAM_TO_UINT16(continuation_handle, stream); 88 continuation_handle = APPLY_CONTINUATION_FLAG(continuation_handle); 89 90 while (remaining_length > max_packet_size) { 91 // Make sure we use the right ACL packet size 92 stream = packet->data + packet->offset; 93 STREAM_SKIP_UINT16(stream); 94 UINT16_TO_STREAM(stream, max_data_size); 95 96 packet->len = max_packet_size; 97 callbacks->fragmented(packet, false); 98 99 packet->offset += max_data_size; 100 remaining_length -= max_data_size; 101 packet->len = remaining_length; 102 103 // Write the ACL header for the next fragment 104 stream = packet->data + packet->offset; 105 UINT16_TO_STREAM(stream, continuation_handle); 106 UINT16_TO_STREAM(stream, remaining_length - HCI_ACL_PREAMBLE_SIZE); 107 108 // Apparently L2CAP can set layer_specific to a max number of segments to transmit 109 if (packet->layer_specific) { 110 packet->layer_specific--; 111 112 if (packet->layer_specific == 0) { 113 packet->event = MSG_HC_TO_STACK_L2C_SEG_XMIT; 114 callbacks->transmit_finished(packet, false); 115 return; 116 } 117 } 118 } 119 120 callbacks->fragmented(packet, true); 121 } 122 123 static bool check_uint16_overflow(uint16_t a, uint16_t b) { 124 return (UINT16_MAX - a) < b; 125 } 126 127 static void reassemble_and_dispatch(UNUSED_ATTR BT_HDR *packet) { 128 if ((packet->event & MSG_EVT_MASK) == MSG_HC_TO_STACK_HCI_ACL) { 129 uint8_t *stream = packet->data; 130 uint16_t handle; 131 uint16_t l2cap_length; 132 uint16_t acl_length; 133 134 STREAM_TO_UINT16(handle, stream); 135 STREAM_TO_UINT16(acl_length, stream); 136 STREAM_TO_UINT16(l2cap_length, stream); 137 138 assert(acl_length == packet->len - HCI_ACL_PREAMBLE_SIZE); 139 140 uint8_t boundary_flag = GET_BOUNDARY_FLAG(handle); 141 handle = handle & HANDLE_MASK; 142 143 BT_HDR *partial_packet = (BT_HDR *)hash_map_get(partial_packets, (void *)(uintptr_t)handle); 144 145 if (boundary_flag == START_PACKET_BOUNDARY) { 146 if (partial_packet) { 147 LOG_WARN(LOG_TAG, "%s found unfinished packet for handle with start packet. Dropping old.", __func__); 148 149 hash_map_erase(partial_packets, (void *)(uintptr_t)handle); 150 buffer_allocator->free(partial_packet); 151 } 152 153 if (acl_length < L2CAP_HEADER_SIZE) { 154 LOG_WARN(LOG_TAG, "%s L2CAP packet too small (%d < %d). Dropping it.", __func__, packet->len, L2CAP_HEADER_SIZE); 155 buffer_allocator->free(packet); 156 return; 157 } 158 159 uint16_t full_length = l2cap_length + L2CAP_HEADER_SIZE + HCI_ACL_PREAMBLE_SIZE; 160 161 // Check for buffer overflow and that the full packet size + BT_HDR size is less than 162 // the max buffer size 163 if (check_uint16_overflow(l2cap_length, (L2CAP_HEADER_SIZE + HCI_ACL_PREAMBLE_SIZE)) || 164 ((full_length + sizeof(BT_HDR)) > BT_DEFAULT_BUFFER_SIZE)) { 165 LOG_ERROR(LOG_TAG, "%s L2CAP packet has invalid length (%d). Dropping it.", __func__, l2cap_length); 166 buffer_allocator->free(packet); 167 return; 168 } 169 170 if (full_length <= packet->len) { 171 if (full_length < packet->len) 172 LOG_WARN(LOG_TAG, "%s found l2cap full length %d less than the hci length %d.", __func__, l2cap_length, packet->len); 173 174 callbacks->reassembled(packet); 175 return; 176 } 177 178 partial_packet = (BT_HDR *)buffer_allocator->alloc(full_length + sizeof(BT_HDR)); 179 partial_packet->event = packet->event; 180 partial_packet->len = full_length; 181 partial_packet->offset = packet->len; 182 183 memcpy(partial_packet->data, packet->data, packet->len); 184 185 // Update the ACL data size to indicate the full expected length 186 stream = partial_packet->data; 187 STREAM_SKIP_UINT16(stream); // skip the handle 188 UINT16_TO_STREAM(stream, full_length - HCI_ACL_PREAMBLE_SIZE); 189 190 hash_map_set(partial_packets, (void *)(uintptr_t)handle, partial_packet); 191 // Free the old packet buffer, since we don't need it anymore 192 buffer_allocator->free(packet); 193 } else { 194 if (!partial_packet) { 195 LOG_WARN(LOG_TAG, "%s got continuation for unknown packet. Dropping it.", __func__); 196 buffer_allocator->free(packet); 197 return; 198 } 199 200 packet->offset = HCI_ACL_PREAMBLE_SIZE; 201 uint16_t projected_offset = partial_packet->offset + (packet->len - HCI_ACL_PREAMBLE_SIZE); 202 if (projected_offset > partial_packet->len) { // len stores the expected length 203 LOG_WARN(LOG_TAG, "%s got packet which would exceed expected length of %d. Truncating.", __func__, partial_packet->len); 204 packet->len = partial_packet->len - partial_packet->offset; 205 projected_offset = partial_packet->len; 206 } 207 208 memcpy( 209 partial_packet->data + partial_packet->offset, 210 packet->data + packet->offset, 211 packet->len - packet->offset 212 ); 213 214 // Free the old packet buffer, since we don't need it anymore 215 buffer_allocator->free(packet); 216 partial_packet->offset = projected_offset; 217 218 if (partial_packet->offset == partial_packet->len) { 219 hash_map_erase(partial_packets, (void *)(uintptr_t)handle); 220 partial_packet->offset = 0; 221 callbacks->reassembled(partial_packet); 222 } 223 } 224 } else { 225 callbacks->reassembled(packet); 226 } 227 } 228 229 static const packet_fragmenter_t interface = { 230 init, 231 cleanup, 232 233 fragment_and_dispatch, 234 reassemble_and_dispatch 235 }; 236 237 const packet_fragmenter_t *packet_fragmenter_get_interface() { 238 controller = controller_get_interface(); 239 buffer_allocator = buffer_allocator_get_interface(); 240 return &interface; 241 } 242 243 const packet_fragmenter_t *packet_fragmenter_get_test_interface( 244 const controller_t *controller_interface, 245 const allocator_t *buffer_allocator_interface) { 246 controller = controller_interface; 247 buffer_allocator = buffer_allocator_interface; 248 return &interface; 249 } 250