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_inject"
     20 
     21 #include "hci_inject.h"
     22 
     23 #include <assert.h>
     24 #include <errno.h>
     25 #include <string.h>
     26 
     27 #include "bt_types.h"
     28 #include "buffer_allocator.h"
     29 #include "hci_layer.h"
     30 #include "osi/include/allocator.h"
     31 #include "osi/include/list.h"
     32 #include "osi/include/log.h"
     33 #include "osi/include/osi.h"
     34 #include "osi/include/socket.h"
     35 #include "osi/include/thread.h"
     36 
     37 typedef enum {
     38   HCI_PACKET_COMMAND  = 1,
     39   HCI_PACKET_ACL_DATA = 2,
     40   HCI_PACKET_SCO_DATA = 3,
     41   HCI_PACKET_EVENT    = 4,
     42 } hci_packet_t;
     43 
     44 typedef struct {
     45   socket_t *socket;
     46   uint8_t buffer[65536 + 3];  // 2 bytes length prefix, 1 byte type prefix.
     47   size_t buffer_size;
     48 } client_t;
     49 
     50 static const port_t LISTEN_PORT = 8873;
     51 
     52 static const hci_inject_t interface;
     53 static const hci_t *hci;
     54 static const allocator_t *buffer_allocator;
     55 static socket_t *listen_socket;
     56 static thread_t *thread;
     57 static list_t *clients;
     58 
     59 static int hci_packet_to_event(hci_packet_t packet);
     60 static void accept_ready(socket_t *socket, void *context);
     61 static void read_ready(socket_t *socket, void *context);
     62 static void client_free(void *ptr);
     63 
     64 bool hci_inject_open(const hci_t *hci_interface) {
     65 #if (!defined(BT_NET_DEBUG) || (BT_NET_DEBUG != TRUE))
     66   return true;          // Disable using network sockets for security reasons
     67 #endif
     68 
     69   assert(listen_socket == NULL);
     70   assert(thread == NULL);
     71   assert(clients == NULL);
     72   assert(hci_interface != NULL);
     73 
     74   hci = hci_interface;
     75 
     76   thread = thread_new("hci_inject");
     77   if (!thread)
     78     goto error;
     79 
     80   clients = list_new(client_free);
     81   if (!clients)
     82     goto error;
     83 
     84   listen_socket = socket_new();
     85   if (!listen_socket)
     86     goto error;
     87 
     88   if (!socket_listen(listen_socket, LISTEN_PORT))
     89     goto error;
     90 
     91   socket_register(listen_socket, thread_get_reactor(thread), NULL, accept_ready, NULL);
     92   return true;
     93 
     94 error:;
     95   interface.close();
     96   return false;
     97 }
     98 
     99 void hci_inject_close(void) {
    100 #if (!defined(BT_NET_DEBUG) || (BT_NET_DEBUG != TRUE))
    101   return;               // Disable using network sockets for security reasons
    102 #endif
    103 
    104   socket_free(listen_socket);
    105   list_free(clients);
    106   thread_free(thread);
    107 
    108   listen_socket = NULL;
    109   thread = NULL;
    110   clients = NULL;
    111 }
    112 
    113 static int hci_packet_to_event(hci_packet_t packet) {
    114   switch (packet) {
    115     case HCI_PACKET_COMMAND:
    116       return MSG_STACK_TO_HC_HCI_CMD;
    117     case HCI_PACKET_ACL_DATA:
    118       return MSG_STACK_TO_HC_HCI_ACL;
    119     case HCI_PACKET_SCO_DATA:
    120       return MSG_STACK_TO_HC_HCI_SCO;
    121     default:
    122       LOG_ERROR(LOG_TAG, "%s unsupported packet type: %d", __func__, packet);
    123       return -1;
    124   }
    125 }
    126 
    127 static void accept_ready(socket_t *socket, UNUSED_ATTR void *context) {
    128   assert(socket != NULL);
    129   assert(socket == listen_socket);
    130 
    131   socket = socket_accept(socket);
    132   if (!socket)
    133     return;
    134 
    135   client_t *client = (client_t *)osi_calloc(sizeof(client_t));
    136 
    137   client->socket = socket;
    138 
    139   if (!list_append(clients, client)) {
    140     LOG_ERROR(LOG_TAG, "%s unable to add client to list.", __func__);
    141     client_free(client);
    142     return;
    143   }
    144 
    145   socket_register(socket, thread_get_reactor(thread), client, read_ready, NULL);
    146 }
    147 
    148 static void read_ready(UNUSED_ATTR socket_t *socket, void *context) {
    149   assert(socket != NULL);
    150   assert(context != NULL);
    151 
    152   client_t *client = (client_t *)context;
    153 
    154   ssize_t ret = socket_read(client->socket, client->buffer + client->buffer_size, sizeof(client->buffer) - client->buffer_size);
    155   if (ret == 0 || (ret == -1 && ret != EWOULDBLOCK && ret != EAGAIN)) {
    156     list_remove(clients, client);
    157     return;
    158   }
    159   client->buffer_size += ret;
    160 
    161   while (client->buffer_size > 3) {
    162     uint8_t *buffer = client->buffer;
    163     hci_packet_t packet_type = (hci_packet_t)buffer[0];
    164     size_t packet_len = (buffer[2] << 8) | buffer[1];
    165     size_t frame_len = 3 + packet_len;
    166 
    167     if (client->buffer_size < frame_len)
    168       break;
    169 
    170     // TODO(sharvil): validate incoming HCI messages.
    171     // TODO(sharvil): once we have an HCI parser, we can eliminate
    172     //   the 2-byte size field since it will be contained in the packet.
    173 
    174     BT_HDR *buf = (BT_HDR *)buffer_allocator->alloc(BT_HDR_SIZE + packet_len);
    175     if (buf) {
    176       buf->event = hci_packet_to_event(packet_type);
    177       buf->offset = 0;
    178       buf->layer_specific = 0;
    179       buf->len = packet_len;
    180       memcpy(buf->data, buffer + 3, packet_len);
    181       hci->transmit_downward(buf->event, buf);
    182     } else {
    183       LOG_ERROR(LOG_TAG, "%s dropping injected packet of length %zu", __func__, packet_len);
    184     }
    185 
    186     size_t remainder = client->buffer_size - frame_len;
    187     memmove(buffer, buffer + frame_len, remainder);
    188     client->buffer_size -= frame_len;
    189   }
    190 }
    191 
    192 static void client_free(void *ptr) {
    193   if (!ptr)
    194     return;
    195 
    196   client_t *client = (client_t *)ptr;
    197   socket_free(client->socket);
    198   osi_free(client);
    199 }
    200 
    201 static const hci_inject_t interface = {
    202   hci_inject_open,
    203   hci_inject_close
    204 };
    205 
    206 const hci_inject_t *hci_inject_get_interface() {
    207   buffer_allocator = buffer_allocator_get_interface();
    208   return &interface;
    209 }
    210