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