Home | History | Annotate | Download | only in src
      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 <base/logging.h>
     24 #include <string.h>
     25 #include <unordered_map>
     26 
     27 #include "bt_target.h"
     28 #include "buffer_allocator.h"
     29 #include "device/include/controller.h"
     30 #include "hci_internals.h"
     31 #include "osi/include/log.h"
     32 #include "osi/include/osi.h"
     33 
     34 #define APPLY_CONTINUATION_FLAG(handle) (((handle)&0xCFFF) | 0x1000)
     35 #define APPLY_START_FLAG(handle) (((handle)&0xCFFF) | 0x2000)
     36 #define SUB_EVENT(event) ((event)&MSG_SUB_EVT_MASK)
     37 #define GET_BOUNDARY_FLAG(handle) (((handle) >> 12) & 0x0003)
     38 
     39 #define HANDLE_MASK 0x0FFF
     40 #define START_PACKET_BOUNDARY 2
     41 #define CONTINUATION_PACKET_BOUNDARY 1
     42 #define L2CAP_HEADER_SIZE 4
     43 
     44 // Our interface and callbacks
     45 
     46 static const allocator_t* buffer_allocator;
     47 static const controller_t* controller;
     48 static const packet_fragmenter_callbacks_t* callbacks;
     49 
     50 static std::unordered_map<uint16_t /* handle */, BT_HDR*> partial_packets;
     51 
     52 static void init(const packet_fragmenter_callbacks_t* result_callbacks) {
     53   callbacks = result_callbacks;
     54 }
     55 
     56 static void cleanup() { partial_packets.clear(); }
     57 
     58 static void fragment_and_dispatch(BT_HDR* packet) {
     59   CHECK(packet != NULL);
     60 
     61   uint16_t event = packet->event & MSG_EVT_MASK;
     62   uint8_t* stream = packet->data + packet->offset;
     63 
     64   // We only fragment ACL packets
     65   if (event != MSG_STACK_TO_HC_HCI_ACL) {
     66     callbacks->fragmented(packet, true);
     67     return;
     68   }
     69 
     70   uint16_t max_data_size =
     71       SUB_EVENT(packet->event) == LOCAL_BR_EDR_CONTROLLER_ID
     72           ? controller->get_acl_data_size_classic()
     73           : controller->get_acl_data_size_ble();
     74 
     75   uint16_t max_packet_size = max_data_size + HCI_ACL_PREAMBLE_SIZE;
     76   uint16_t remaining_length = packet->len;
     77 
     78   uint16_t continuation_handle;
     79   STREAM_TO_UINT16(continuation_handle, stream);
     80   continuation_handle = APPLY_CONTINUATION_FLAG(continuation_handle);
     81 
     82   while (remaining_length > max_packet_size) {
     83     // Make sure we use the right ACL packet size
     84     stream = packet->data + packet->offset;
     85     STREAM_SKIP_UINT16(stream);
     86     UINT16_TO_STREAM(stream, max_data_size);
     87 
     88     packet->len = max_packet_size;
     89     callbacks->fragmented(packet, false);
     90 
     91     packet->offset += max_data_size;
     92     remaining_length -= max_data_size;
     93     packet->len = remaining_length;
     94 
     95     // Write the ACL header for the next fragment
     96     stream = packet->data + packet->offset;
     97     UINT16_TO_STREAM(stream, continuation_handle);
     98     UINT16_TO_STREAM(stream, remaining_length - HCI_ACL_PREAMBLE_SIZE);
     99 
    100     // Apparently L2CAP can set layer_specific to a max number of segments to
    101     // transmit
    102     if (packet->layer_specific) {
    103       packet->layer_specific--;
    104 
    105       if (packet->layer_specific == 0) {
    106         packet->event = MSG_HC_TO_STACK_L2C_SEG_XMIT;
    107         callbacks->transmit_finished(packet, false);
    108         return;
    109       }
    110     }
    111   }
    112 
    113   callbacks->fragmented(packet, true);
    114 }
    115 
    116 static bool check_uint16_overflow(uint16_t a, uint16_t b) {
    117   return (UINT16_MAX - a) < b;
    118 }
    119 
    120 static void reassemble_and_dispatch(UNUSED_ATTR BT_HDR* packet) {
    121   if ((packet->event & MSG_EVT_MASK) == MSG_HC_TO_STACK_HCI_ACL) {
    122     uint8_t* stream = packet->data;
    123     uint16_t handle;
    124     uint16_t l2cap_length;
    125     uint16_t acl_length;
    126 
    127     STREAM_TO_UINT16(handle, stream);
    128     STREAM_TO_UINT16(acl_length, stream);
    129     STREAM_TO_UINT16(l2cap_length, stream);
    130 
    131     CHECK(acl_length == packet->len - HCI_ACL_PREAMBLE_SIZE);
    132 
    133     uint8_t boundary_flag = GET_BOUNDARY_FLAG(handle);
    134     handle = handle & HANDLE_MASK;
    135 
    136     if (boundary_flag == START_PACKET_BOUNDARY) {
    137       auto map_iter = partial_packets.find(handle);
    138       if (map_iter != partial_packets.end()) {
    139         LOG_WARN(LOG_TAG,
    140                  "%s found unfinished packet for handle with start packet. "
    141                  "Dropping old.",
    142                  __func__);
    143 
    144         BT_HDR* hdl = map_iter->second;
    145         partial_packets.erase(map_iter);
    146         buffer_allocator->free(hdl);
    147       }
    148 
    149       if (acl_length < L2CAP_HEADER_SIZE) {
    150         LOG_WARN(LOG_TAG, "%s L2CAP packet too small (%d < %d). Dropping it.",
    151                  __func__, packet->len, L2CAP_HEADER_SIZE);
    152         buffer_allocator->free(packet);
    153         return;
    154       }
    155 
    156       uint16_t full_length =
    157           l2cap_length + L2CAP_HEADER_SIZE + HCI_ACL_PREAMBLE_SIZE;
    158 
    159       // Check for buffer overflow and that the full packet size + BT_HDR size
    160       // is less than the max buffer size
    161       if (check_uint16_overflow(l2cap_length,
    162                                 (L2CAP_HEADER_SIZE + HCI_ACL_PREAMBLE_SIZE)) ||
    163           ((full_length + sizeof(BT_HDR)) > BT_DEFAULT_BUFFER_SIZE)) {
    164         LOG_ERROR(LOG_TAG, "%s Dropping L2CAP packet with invalid length (%d).",
    165                   __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,
    173                    "%s found l2cap full length %d less than the hci length %d.",
    174                    __func__, l2cap_length, packet->len);
    175 
    176         callbacks->reassembled(packet);
    177         return;
    178       }
    179 
    180       BT_HDR* partial_packet =
    181           (BT_HDR*)buffer_allocator->alloc(full_length + sizeof(BT_HDR));
    182       partial_packet->event = packet->event;
    183       partial_packet->len = full_length;
    184       partial_packet->offset = packet->len;
    185 
    186       memcpy(partial_packet->data, packet->data, packet->len);
    187 
    188       // Update the ACL data size to indicate the full expected length
    189       stream = partial_packet->data;
    190       STREAM_SKIP_UINT16(stream);  // skip the handle
    191       UINT16_TO_STREAM(stream, full_length - HCI_ACL_PREAMBLE_SIZE);
    192 
    193       partial_packets[handle] = partial_packet;
    194 
    195       // Free the old packet buffer, since we don't need it anymore
    196       buffer_allocator->free(packet);
    197     } else {
    198       auto map_iter = partial_packets.find(handle);
    199       if (map_iter == partial_packets.end()) {
    200         LOG_WARN(LOG_TAG,
    201                  "%s got continuation for unknown packet. Dropping it.",
    202                  __func__);
    203         buffer_allocator->free(packet);
    204         return;
    205       }
    206       BT_HDR* partial_packet = map_iter->second;
    207 
    208       packet->offset = HCI_ACL_PREAMBLE_SIZE;
    209       uint16_t projected_offset =
    210           partial_packet->offset + (packet->len - HCI_ACL_PREAMBLE_SIZE);
    211       if (projected_offset >
    212           partial_packet->len) {  // len stores the expected length
    213         LOG_WARN(LOG_TAG,
    214                  "%s got packet which would exceed expected length of %d. "
    215                  "Truncating.",
    216                  __func__, partial_packet->len);
    217         packet->len = partial_packet->len - partial_packet->offset;
    218         projected_offset = partial_packet->len;
    219       }
    220 
    221       memcpy(partial_packet->data + partial_packet->offset,
    222              packet->data + packet->offset, packet->len - packet->offset);
    223 
    224       // Free the old packet buffer, since we don't need it anymore
    225       buffer_allocator->free(packet);
    226       partial_packet->offset = projected_offset;
    227 
    228       if (partial_packet->offset == partial_packet->len) {
    229         partial_packets.erase(handle);
    230         partial_packet->offset = 0;
    231         callbacks->reassembled(partial_packet);
    232       }
    233     }
    234   } else {
    235     callbacks->reassembled(packet);
    236   }
    237 }
    238 
    239 static const packet_fragmenter_t interface = {init, cleanup,
    240 
    241                                               fragment_and_dispatch,
    242                                               reassemble_and_dispatch};
    243 
    244 const packet_fragmenter_t* packet_fragmenter_get_interface() {
    245   controller = controller_get_interface();
    246   buffer_allocator = buffer_allocator_get_interface();
    247   return &interface;
    248 }
    249 
    250 const packet_fragmenter_t* packet_fragmenter_get_test_interface(
    251     const controller_t* controller_interface,
    252     const allocator_t* buffer_allocator_interface) {
    253   controller = controller_interface;
    254   buffer_allocator = buffer_allocator_interface;
    255   return &interface;
    256 }
    257