1 2 // hal_cpu 3 #include "hal_cpu.h" 4 void hal_cpu_disable_irqs(void){} 5 void hal_cpu_enable_irqs(void){} 6 void hal_cpu_enable_irqs_and_sleep(void){} 7 8 // mock_sm.c 9 #include "ble/sm.h" 10 void sm_add_event_handler(btstack_packet_callback_registration_t * callback_handler){} 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); 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 } 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 } 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 } 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 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 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 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 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 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 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 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 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 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 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 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 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 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 } 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 310 int main (int argc, const char * argv[]){ 311 return CommandLineTestRunner::RunAllTests(argc, argv); 312 } 313