1
2 // hal_cpu
3 #include "hal_cpu.h"
hal_cpu_disable_irqs(void)4 void hal_cpu_disable_irqs(void){}
hal_cpu_enable_irqs(void)5 void hal_cpu_enable_irqs(void){}
hal_cpu_enable_irqs_and_sleep(void)6 void hal_cpu_enable_irqs_and_sleep(void){}
7
8 // mock_sm.c
9 #include "ble/sm.h"
sm_add_event_handler(btstack_packet_callback_registration_t * callback_handler)10 void sm_add_event_handler(btstack_packet_callback_registration_t * callback_handler){}
sm_request_pairing(hci_con_handle_t con_handle)11 void sm_request_pairing(hci_con_handle_t con_handle){}
12
13 // mock_hci_transport.h
14 #include "hci_transport.h"
15 void mock_hci_transport_receive_packet(uint8_t packet_type, uint8_t * packet, uint16_t size);
16 const hci_transport_t * mock_hci_transport_mock_get_instance(void);
17
18 // mock_hci_transport.c
19 #include <stddef.h>
20 static uint8_t mock_hci_transport_outgoing_packet_buffer[HCI_ACL_PAYLOAD_SIZE];
21 static uint16_t mock_hci_transport_outgoing_packet_size;
22 static uint8_t mock_hci_transport_outgoing_packet_type;
23
24 static void (*mock_hci_transport_packet_handler)(uint8_t packet_type, uint8_t * packet, uint16_t size);
mock_hci_transport_register_packet_handler(void (* packet_handler)(uint8_t packet_type,uint8_t * packet,uint16_t size))25 static void mock_hci_transport_register_packet_handler(void (*packet_handler)(uint8_t packet_type, uint8_t * packet, uint16_t size)){
26 mock_hci_transport_packet_handler = packet_handler;
27 }
mock_hci_transport_send_packet(uint8_t packet_type,uint8_t * packet,int size)28 static int mock_hci_transport_send_packet(uint8_t packet_type, uint8_t *packet, int size){
29 mock_hci_transport_outgoing_packet_type = packet_type;
30 mock_hci_transport_outgoing_packet_size = size;
31 memcpy(mock_hci_transport_outgoing_packet_buffer, packet, size);
32 return 0;
33 }
mock_hci_transport_mock_get_instance(void)34 const hci_transport_t * mock_hci_transport_mock_get_instance(void){
35 static hci_transport_t mock_hci_transport = {
36 /* .transport.name = */ "mock",
37 /* .transport.init = */ NULL,
38 /* .transport.open = */ NULL,
39 /* .transport.close = */ NULL,
40 /* .transport.register_packet_handler = */ &mock_hci_transport_register_packet_handler,
41 /* .transport.can_send_packet_now = */ NULL,
42 /* .transport.send_packet = */ &mock_hci_transport_send_packet,
43 /* .transport.set_baudrate = */ NULL,
44 };
45 return &mock_hci_transport;
46 }
mock_hci_transport_receive_packet(uint8_t packet_type,const uint8_t * packet,uint16_t size)47 void mock_hci_transport_receive_packet(uint8_t packet_type, const uint8_t * packet, uint16_t size){
48 (*mock_hci_transport_packet_handler)(packet_type, (uint8_t *) packet, size);
49 }
50
51 //
52
53 #include <stdint.h>
54 #include <stdio.h>
55 #include <stdlib.h>
56 #include <string.h>
57
58 #include "CppUTest/TestHarness.h"
59 #include "CppUTest/CommandLineTestRunner.h"
60 #include "CppUTestExt/MockSupport.h"
61
62 #include "hci_dump.h"
63 #include "btstack_debug.h"
64 #include "l2cap.h"
65 #include "btstack_memory.h"
66 #include "btstack_run_loop_embedded.h"
67 #include "hci_dump_posix_stdout.h"
68 #include "btstack_event.h"
69
70 #define TEST_PACKET_SIZE 100
71 #define HCI_CON_HANDLE_TEST_LE 0x0005
72 #define TEST_PSM 0x1001
73
74 static bool l2cap_channel_accept_incoming;
75 static uint16_t initial_credits = L2CAP_LE_AUTOMATIC_CREDITS;
76 static uint8_t data_channel_buffer[TEST_PACKET_SIZE];
77 static uint16_t l2cap_cid;
78 static bool l2cap_channel_opened;
79 static btstack_packet_callback_registration_t l2cap_event_callback_registration;
80
81 // l2cap fuzz api
82 extern "C" void l2cap_setup_test_channels_fuzz(void);
83 extern "C" void l2cap_free_channels_fuzz(void);
84 extern "C" l2cap_channel_t * l2cap_get_dynamic_channel_fuzz(void);
85
86 // l2cap random public function
87 extern "C" void l2cap_finalize_channel_close(l2cap_channel_t * channel);
88
89 const uint8_t le_data_channel_conn_request_1[] = {
90 0x05, 0x20, 0x12, 0x00, 0x0e, 0x00, 0x05, 0x00, 0x14, 0x01, 0x0a, 0x00, 0x01, 0x10, 0x41, 0x00,
91 0x64, 0x00, 0x30, 0x00, 0xff, 0xff
92 };
93
94 const uint8_t le_data_channel_invalid_pdu[] = {
95 0x05, 0x20, 0x12, 0x00, 0x0e, 0x00, 0x05, 0x00, 0x11, 0x01, 0x0a, 0x00, 0x01, 0x10, 0x41, 0x00,
96 0x64, 0x00, 0x30, 0x00, 0xff, 0xff
97 };
98
99 const uint8_t le_data_channel_conn_response_1[] = {
100 0x05, 0x20, 0x12, 0x00, 0x0e, 0x00, 0x05, 0x00, 0x15, 0x01, 0x0a, 0x00, 0x41, 0x00, 0x64, 0x00,
101 0x30, 0x00, 0xff, 0xff, 0x00, 0x00
102 };
103
104 const uint8_t le_data_channel_data_1[] = {
105 0x05, 0x20, 0x04, 0x00, 0x00, 0x00, 0x41, 0x00
106 };
107
fix_boundary_flags(uint8_t * packet,uint16_t size)108 static void fix_boundary_flags(uint8_t * packet, uint16_t size){
109 uint8_t acl_flags = packet[1] >> 4;
110 if (acl_flags == 0){
111 acl_flags = 2; // first fragment
112 }
113 packet[1] = (packet[1] & 0x0f) | (acl_flags << 4);
114 }
115
print_acl(const char * name,const uint8_t * packet,uint16_t size)116 static void print_acl(const char * name, const uint8_t * packet, uint16_t size){
117 printf("const uint8_t %s[] = {", name);
118 uint16_t i;
119 for (i=0;i<size;i++){
120 if (i != 0){
121 printf(", ");
122 }
123 if ((i % 16) == 0){
124 printf("\n ");
125 }
126 printf("0x%02x", packet[i]);
127 }
128 printf("\n};\n");
129 }
130
l2cap_channel_packet_handler(uint8_t packet_type,uint16_t channel,uint8_t * packet,uint16_t size)131 static void l2cap_channel_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
132 UNUSED(channel);
133 UNUSED(size);
134 uint16_t cid;
135 switch (packet_type) {
136 case HCI_EVENT_PACKET:
137 switch (hci_event_packet_get_type(packet)) {
138 case L2CAP_EVENT_CBM_INCOMING_CONNECTION:
139 cid = l2cap_event_cbm_incoming_connection_get_local_cid(packet);
140 if (l2cap_channel_accept_incoming){
141 l2cap_cbm_accept_connection(cid, data_channel_buffer, sizeof(data_channel_buffer), initial_credits);
142 } else {
143 l2cap_cbm_decline_connection(cid, L2CAP_CBM_CONNECTION_RESULT_NO_RESOURCES_AVAILABLE);
144 }
145 break;
146 case L2CAP_EVENT_CBM_CHANNEL_OPENED:
147 l2cap_channel_opened = true;
148 break;
149 default:
150 break;
151 }
152 break;
153 default:
154 break;
155 }
156 }
157
TEST_GROUP(L2CAP_CHANNELS)158 TEST_GROUP(L2CAP_CHANNELS){
159 const hci_transport_t * hci_transport;
160 void setup(void){
161 btstack_memory_init();
162 btstack_run_loop_init(btstack_run_loop_embedded_get_instance());
163 hci_transport = mock_hci_transport_mock_get_instance();
164 hci_init(hci_transport, NULL);
165 l2cap_init();
166 l2cap_event_callback_registration.callback = &l2cap_channel_packet_handler;
167 l2cap_add_event_handler(&l2cap_event_callback_registration);
168 l2cap_register_fixed_channel(&l2cap_channel_packet_handler, L2CAP_CID_ATTRIBUTE_PROTOCOL);
169 hci_dump_init(hci_dump_posix_stdout_get_instance());
170 l2cap_channel_opened = false;
171 }
172 void teardown(void){
173 l2cap_remove_event_handler(&l2cap_event_callback_registration);
174 l2cap_deinit();
175 hci_deinit();
176 btstack_memory_deinit();
177 btstack_run_loop_deinit();
178 }
179 };
180
TEST(L2CAP_CHANNELS,fixed_channel)181 TEST(L2CAP_CHANNELS, fixed_channel){
182 hci_setup_test_connections_fuzz();
183 // channel does not exist
184 l2cap_request_can_send_fix_channel_now_event(HCI_CON_HANDLE_TEST_LE, 0x003f);
185 // att
186 l2cap_request_can_send_fix_channel_now_event(HCI_CON_HANDLE_TEST_LE, L2CAP_CID_ATTRIBUTE_PROTOCOL);
187 //
188 (void) l2cap_can_send_fixed_channel_packet_now(HCI_CON_HANDLE_TEST_LE, L2CAP_CID_ATTRIBUTE_PROTOCOL);
189 // packet buffer not reserved
190 log_info("ignore error in next line (calling .. without reserving buffer first");
191 l2cap_send_prepared_connectionless(HCI_CON_HANDLE_TEST_LE, L2CAP_CID_ATTRIBUTE_PROTOCOL, 5);
192 // packet buffer reserved
193 l2cap_reserve_packet_buffer();
194 l2cap_send_prepared_connectionless(HCI_CON_HANDLE_TEST_LE, L2CAP_CID_ATTRIBUTE_PROTOCOL, 5);
195 //
196 l2cap_send_connectionless(HCI_CON_HANDLE_TEST_LE, L2CAP_CID_ATTRIBUTE_PROTOCOL, (uint8_t *) "hallo", 5);
197 }
198
TEST(L2CAP_CHANNELS,some_functions)199 TEST(L2CAP_CHANNELS, some_functions){
200 hci_setup_test_connections_fuzz();
201 l2cap_reserve_packet_buffer();
202 (void) l2cap_get_outgoing_buffer();
203 l2cap_release_packet_buffer();
204 l2cap_set_max_le_mtu(30);
205 l2cap_set_max_le_mtu(30);
206 l2cap_cbm_unregister_service(TEST_PSM);
207 l2cap_cbm_accept_connection(0X01, NULL, 0, 0);
208 l2cap_cbm_decline_connection(0x01, L2CAP_CBM_CONNECTION_RESULT_NO_RESOURCES_AVAILABLE);
209 l2cap_cbm_available_credits(0x01);
210 l2cap_disconnect(0x01);
211
212 uint16_t credits = 10;
213 uint16_t mtu = 23;
214 uint8_t buffer[10];
215 uint16_t out_local_cid;
216
217 l2cap_le_register_service(&l2cap_channel_packet_handler, TEST_PSM, LEVEL_2);
218 l2cap_le_unregister_service(TEST_PSM);
219 l2cap_le_accept_connection(0X01, buffer, mtu, credits);
220 l2cap_le_decline_connection(0X01);
221 l2cap_le_create_channel(&l2cap_channel_packet_handler, HCI_CON_HANDLE_TEST_LE, TEST_PSM, buffer, mtu, credits, LEVEL_2, &out_local_cid);
222 l2cap_le_provide_credits(0X01, credits);
223 l2cap_le_can_send_now(0X01);
224 l2cap_le_request_can_send_now_event(0X01);
225 l2cap_le_send_data(0X01, (const uint8_t * )buffer, sizeof(buffer));
226 l2cap_le_disconnect(0X01);
227 }
228
TEST(L2CAP_CHANNELS,outgoing_no_connection)229 TEST(L2CAP_CHANNELS, outgoing_no_connection){
230 l2cap_cbm_create_channel(&l2cap_channel_packet_handler, HCI_CON_HANDLE_TEST_LE, TEST_PSM, data_channel_buffer,
231 sizeof(data_channel_buffer), L2CAP_LE_AUTOMATIC_CREDITS, LEVEL_0, &l2cap_cid);
232 }
233
TEST(L2CAP_CHANNELS,outgoing_security_1)234 TEST(L2CAP_CHANNELS, outgoing_security_1){
235 hci_setup_test_connections_fuzz();
236 l2cap_cbm_create_channel(&l2cap_channel_packet_handler, HCI_CON_HANDLE_TEST_LE, TEST_PSM, data_channel_buffer,
237 sizeof(data_channel_buffer), L2CAP_LE_AUTOMATIC_CREDITS, LEVEL_2, NULL);
238 l2cap_cbm_create_channel(&l2cap_channel_packet_handler, HCI_CON_HANDLE_TEST_LE, TEST_PSM, data_channel_buffer,
239 sizeof(data_channel_buffer), L2CAP_LE_AUTOMATIC_CREDITS, LEVEL_2, &l2cap_cid);
240 }
241
TEST(L2CAP_CHANNELS,outgoing_1)242 TEST(L2CAP_CHANNELS, outgoing_1){
243 hci_setup_test_connections_fuzz();
244 l2cap_cbm_create_channel(&l2cap_channel_packet_handler, HCI_CON_HANDLE_TEST_LE, TEST_PSM, data_channel_buffer,
245 sizeof(data_channel_buffer), L2CAP_LE_AUTOMATIC_CREDITS, LEVEL_0, &l2cap_cid);
246 // fix_boundary_flags(mock_hci_transport_outgoing_packet_buffer, mock_hci_transport_outgoing_packet_size);
247 // print_acl("le_data_channel_conn_request_1", mock_hci_transport_outgoing_packet_buffer, mock_hci_transport_outgoing_packet_size);
248 // simulate conn response
249 mock_hci_transport_receive_packet(HCI_ACL_DATA_PACKET, le_data_channel_conn_response_1, sizeof(le_data_channel_conn_response_1));
250 CHECK(l2cap_channel_opened);
251 CHECK(hci_number_free_acl_slots_for_handle(HCI_CON_HANDLE_TEST_LE) > 0);
252 bool can_send_now = l2cap_can_send_packet_now(l2cap_cid);
253 CHECK(can_send_now);
254 l2cap_request_can_send_now_event(l2cap_cid);
255 CHECK(hci_number_free_acl_slots_for_handle(HCI_CON_HANDLE_TEST_LE) > 0);
256 l2cap_send(l2cap_cid, (uint8_t *) "hallo", 5);
257 // CHECK(hci_number_free_acl_slots_for_handle(HCI_CON_HANDLE_TEST) > 0);
258 // fix_boundary_flags(mock_hci_transport_outgoing_packet_buffer, mock_hci_transport_outgoing_packet_size);
259 // print_acl("le_data_channel_data_1", mock_hci_transport_outgoing_packet_buffer, mock_hci_transport_outgoing_packet_size);
260 // simulate data
261 mock_hci_transport_receive_packet(HCI_ACL_DATA_PACKET, le_data_channel_data_1, sizeof(le_data_channel_data_1));
262 l2cap_disconnect(l2cap_cid);
263 }
264
TEST(L2CAP_CHANNELS,incoming_1)265 TEST(L2CAP_CHANNELS, incoming_1){
266 hci_setup_test_connections_fuzz();
267 l2cap_cbm_register_service(&l2cap_channel_packet_handler, TEST_PSM, LEVEL_0);
268 // simulate conn request
269 l2cap_channel_accept_incoming = true;
270 mock_hci_transport_receive_packet(HCI_ACL_DATA_PACKET, le_data_channel_conn_request_1, sizeof(le_data_channel_conn_request_1));
271 // fix_boundary_flags(mock_hci_transport_outgoing_packet_buffer, mock_hci_transport_outgoing_packet_size);
272 // print_acl("le_data_channel_conn_response_1", mock_hci_transport_outgoing_packet_buffer, mock_hci_transport_outgoing_packet_size);
273 // TODO: verify data
274 l2cap_cbm_unregister_service(TEST_PSM);
275 }
276
TEST(L2CAP_CHANNELS,incoming_2)277 TEST(L2CAP_CHANNELS, incoming_2){
278 hci_setup_test_connections_fuzz();
279 l2cap_cbm_register_service(&l2cap_channel_packet_handler, TEST_PSM, LEVEL_2);
280 // simulate conn request
281 l2cap_channel_accept_incoming = true;
282 mock_hci_transport_receive_packet(HCI_ACL_DATA_PACKET, le_data_channel_conn_request_1, sizeof(le_data_channel_conn_request_1));
283 }
284
TEST(L2CAP_CHANNELS,incoming_3)285 TEST(L2CAP_CHANNELS, incoming_3){
286 hci_setup_test_connections_fuzz();
287 l2cap_cbm_register_service(&l2cap_channel_packet_handler, TEST_PSM, LEVEL_0);
288 // simulate conn request
289 l2cap_channel_accept_incoming = true;
290 mock_hci_transport_receive_packet(HCI_ACL_DATA_PACKET, le_data_channel_invalid_pdu, sizeof(le_data_channel_invalid_pdu));
291 }
292
TEST(L2CAP_CHANNELS,incoming_decline)293 TEST(L2CAP_CHANNELS, incoming_decline){
294 hci_setup_test_connections_fuzz();
295 l2cap_cbm_register_service(&l2cap_channel_packet_handler, TEST_PSM, LEVEL_0);
296 // simulate conn request
297 l2cap_channel_accept_incoming = false;
298 mock_hci_transport_receive_packet(HCI_ACL_DATA_PACKET, le_data_channel_conn_request_1, sizeof(le_data_channel_conn_request_1));
299 // fix_boundary_flags(mock_hci_transport_outgoing_packet_buffer, mock_hci_transport_outgoing_packet_size);
300 // print_acl("le_data_channel_conn_response_1", mock_hci_transport_outgoing_packet_buffer, mock_hci_transport_outgoing_packet_size);
301 // TODO: verify data
302 }
TEST(L2CAP_CHANNELS,fuzz)303 TEST(L2CAP_CHANNELS, fuzz) {
304 l2cap_setup_test_channels_fuzz();
305 l2cap_channel_t * channel = l2cap_get_dynamic_channel_fuzz();
306 l2cap_free_channels_fuzz();
307 l2cap_get_dynamic_channel_fuzz();
308 }
309
main(int argc,const char * argv[])310 int main (int argc, const char * argv[]){
311 return CommandLineTestRunner::RunAllTests(argc, argv);
312 }
313