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
36 typedef 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
43 typedef 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
49 static const port_t LISTEN_PORT = 8873;
50
51 static const hci_inject_t interface;
52 static const hci_t *hci;
53 static const allocator_t *buffer_allocator;
54 static socket_t *listen_socket;
55 static thread_t *thread;
56 static list_t *clients;
57
58 static int hci_packet_to_event(hci_packet_t packet);
59 static void accept_ready(socket_t *socket, void *context);
60 static void read_ready(socket_t *socket, void *context);
61 static void client_free(void *ptr);
62
hci_inject_open(const hci_t * hci_interface)63 bool 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
93 error:;
94 interface.close();
95 return false;
96 }
97
hci_inject_close(void)98 void 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
hci_packet_to_event(hci_packet_t packet)112 static 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
accept_ready(socket_t * socket,UNUSED_ATTR void * context)126 static 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
read_ready(UNUSED_ATTR socket_t * socket,void * context)152 static 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
client_free(void * ptr)196 static 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
205 static const hci_inject_t interface = {
206 hci_inject_open,
207 hci_inject_close
208 };
209
hci_inject_get_interface()210 const hci_inject_t *hci_inject_get_interface() {
211 buffer_allocator = buffer_allocator_get_interface();
212 return &interface;
213 }
214