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 <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_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 bool hci_inject_open(const hci_t* hci_interface);
51 static void hci_inject_close(void);
52 static int hci_packet_to_event(hci_packet_t packet);
53 static void accept_ready(socket_t* socket, void* context);
54 static void read_ready(socket_t* socket, void* context);
55 static void client_free(void* ptr);
56
57 static const port_t LISTEN_PORT = 8873;
58
59 static const hci_inject_t interface = {hci_inject_open, hci_inject_close};
60
61 static const hci_t* hci;
62 static const allocator_t* buffer_allocator;
63 static socket_t* listen_socket;
64 static thread_t* thread;
65 static list_t* clients;
66
hci_inject_open(const hci_t * hci_interface)67 static bool hci_inject_open(const hci_t* hci_interface) {
68 #if (BT_NET_DEBUG != TRUE)
69 return true; // Disable using network sockets for security reasons
70 #endif
71
72 CHECK(listen_socket == NULL);
73 CHECK(thread == NULL);
74 CHECK(clients == NULL);
75 CHECK(hci_interface != NULL);
76
77 hci = hci_interface;
78
79 thread = thread_new("hci_inject");
80 if (!thread) goto error;
81
82 clients = list_new(client_free);
83 if (!clients) goto error;
84
85 listen_socket = socket_new();
86 if (!listen_socket) goto error;
87
88 if (!socket_listen(listen_socket, LISTEN_PORT)) goto error;
89
90 socket_register(listen_socket, thread_get_reactor(thread), NULL, accept_ready,
91 NULL);
92 return true;
93
94 error:;
95 interface.close();
96 return false;
97 }
98
hci_inject_close(void)99 static void hci_inject_close(void) {
100 #if (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
hci_packet_to_event(hci_packet_t packet)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
accept_ready(socket_t * socket,UNUSED_ATTR void * context)127 static void accept_ready(socket_t* socket, UNUSED_ATTR void* context) {
128 CHECK(socket != NULL);
129 CHECK(socket == listen_socket);
130
131 socket = socket_accept(socket);
132 if (!socket) return;
133
134 client_t* client = (client_t*)osi_calloc(sizeof(client_t));
135
136 client->socket = socket;
137
138 if (!list_append(clients, client)) {
139 LOG_ERROR(LOG_TAG, "%s unable to add client to list.", __func__);
140 client_free(client);
141 return;
142 }
143
144 socket_register(socket, thread_get_reactor(thread), client, read_ready, NULL);
145 }
146
read_ready(UNUSED_ATTR socket_t * socket,void * context)147 static void read_ready(UNUSED_ATTR socket_t* socket, void* context) {
148 CHECK(socket != NULL);
149 CHECK(context != NULL);
150
151 client_t* client = (client_t*)context;
152
153 ssize_t ret =
154 socket_read(client->socket, client->buffer + client->buffer_size,
155 sizeof(client->buffer) - client->buffer_size);
156 if (ret == 0 || (ret == -1 && ret != EWOULDBLOCK && ret != EAGAIN)) {
157 list_remove(clients, client);
158 return;
159 }
160 client->buffer_size += ret;
161
162 while (client->buffer_size > 3) {
163 uint8_t* buffer = client->buffer;
164 hci_packet_t packet_type = (hci_packet_t)buffer[0];
165 size_t packet_len = (buffer[2] << 8) | buffer[1];
166 size_t frame_len = 3 + packet_len;
167
168 if (client->buffer_size < frame_len) 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__,
184 packet_len);
185 }
186
187 size_t remainder = client->buffer_size - frame_len;
188 memmove(buffer, buffer + frame_len, remainder);
189 client->buffer_size -= frame_len;
190 }
191 }
192
client_free(void * ptr)193 static void client_free(void* ptr) {
194 if (!ptr) return;
195
196 client_t* client = (client_t*)ptr;
197 socket_free(client->socket);
198 osi_free(client);
199 }
200
hci_inject_get_interface()201 const hci_inject_t* hci_inject_get_interface() {
202 buffer_allocator = buffer_allocator_get_interface();
203 return &interface;
204 }
205