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