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