xref: /btstack/example/le_mitm.c (revision bba48196553c8cb4568b4278b9e099c548e7c432)
107f151d6SMatthias Ringwald /*
207f151d6SMatthias Ringwald  * Copyright (C) 2019 BlueKitchen GmbH
307f151d6SMatthias Ringwald  *
407f151d6SMatthias Ringwald  * Redistribution and use in source and binary forms, with or without
507f151d6SMatthias Ringwald  * modification, are permitted provided that the following conditions
607f151d6SMatthias Ringwald  * are met:
707f151d6SMatthias Ringwald  *
807f151d6SMatthias Ringwald  * 1. Redistributions of source code must retain the above copyright
907f151d6SMatthias Ringwald  *    notice, this list of conditions and the following disclaimer.
1007f151d6SMatthias Ringwald  * 2. Redistributions in binary form must reproduce the above copyright
1107f151d6SMatthias Ringwald  *    notice, this list of conditions and the following disclaimer in the
1207f151d6SMatthias Ringwald  *    documentation and/or other materials provided with the distribution.
1307f151d6SMatthias Ringwald  * 3. Neither the name of the copyright holders nor the names of
1407f151d6SMatthias Ringwald  *    contributors may be used to endorse or promote products derived
1507f151d6SMatthias Ringwald  *    from this software without specific prior written permission.
1607f151d6SMatthias Ringwald  * 4. Any redistribution, use, or modification is done solely for
1707f151d6SMatthias Ringwald  *    personal benefit and not for any commercial purpose or for
1807f151d6SMatthias Ringwald  *    monetary gain.
1907f151d6SMatthias Ringwald  *
2007f151d6SMatthias Ringwald  * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS
2107f151d6SMatthias Ringwald  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
2207f151d6SMatthias Ringwald  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
232fca4dadSMilanka Ringwald  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BLUEKITCHEN
242fca4dadSMilanka Ringwald  * GMBH OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
2507f151d6SMatthias Ringwald  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
2607f151d6SMatthias Ringwald  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
2707f151d6SMatthias Ringwald  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
2807f151d6SMatthias Ringwald  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
2907f151d6SMatthias Ringwald  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
3007f151d6SMatthias Ringwald  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3107f151d6SMatthias Ringwald  * SUCH DAMAGE.
3207f151d6SMatthias Ringwald  *
3307f151d6SMatthias Ringwald  * Please inquire about commercial licensing options at
3407f151d6SMatthias Ringwald  * [email protected]
3507f151d6SMatthias Ringwald  *
3607f151d6SMatthias Ringwald  */
3707f151d6SMatthias Ringwald 
3807f151d6SMatthias Ringwald #define BTSTACK_FILE__ "le_mitm.c"
3907f151d6SMatthias Ringwald 
4007f151d6SMatthias Ringwald // *****************************************************************************
41ec8ae085SMilanka Ringwald /* EXAMPLE_START(le_mitm): LE Man-in-the-Middle Tool
4207f151d6SMatthias Ringwald  *
4307f151d6SMatthias Ringwald  * @text The example first does an LE scan and allows the user to select a Peripheral
4407f151d6SMatthias Ringwald  * device. Then, it connects to the Peripheral and starts advertising with the same
4507f151d6SMatthias Ringwald  * data as the Peripheral device.
4607f151d6SMatthias Ringwald  * ATT Requests and responses are forwarded between the peripheral and the central
4707f151d6SMatthias Ringwald  * Security requests are handled locally.
4807f151d6SMatthias Ringwald  *
4907f151d6SMatthias Ringwald  * @note A Bluetooth Controller that supports Central and Peripheral Role
5007f151d6SMatthias Ringwald  * at the same time is required for this example. See chipset/README.md
5107f151d6SMatthias Ringwald  *
5207f151d6SMatthias Ringwald  */
5307f151d6SMatthias Ringwald // *****************************************************************************
5407f151d6SMatthias Ringwald 
5507f151d6SMatthias Ringwald 
5607f151d6SMatthias Ringwald #include <inttypes.h>
5707f151d6SMatthias Ringwald #include <stdint.h>
5807f151d6SMatthias Ringwald #include <stdio.h>
5907f151d6SMatthias Ringwald #include <string.h>
6007f151d6SMatthias Ringwald 
6107f151d6SMatthias Ringwald #include "btstack.h"
6207f151d6SMatthias Ringwald 
6307f151d6SMatthias Ringwald // Number of devices shown during scanning
6407f151d6SMatthias Ringwald #define MAX_NUM_DEVICES 36
6507f151d6SMatthias Ringwald 
6607f151d6SMatthias Ringwald // Max number of ATT PTUs to queue (if malloc is not used)
6707f151d6SMatthias Ringwald #define MAX_NUM_ATT_PDUS 20
6807f151d6SMatthias Ringwald 
6907f151d6SMatthias Ringwald // Max ATT MTU - can be increased if needed
7007f151d6SMatthias Ringwald #define MAX_ATT_MTU ATT_DEFAULT_MTU
7107f151d6SMatthias Ringwald 
7207f151d6SMatthias Ringwald typedef struct {
7307f151d6SMatthias Ringwald     bd_addr_t addr;
7407f151d6SMatthias Ringwald     bd_addr_type_t addr_type;
7507f151d6SMatthias Ringwald     int8_t  rssi;
7607f151d6SMatthias Ringwald     uint8_t ad_len;
7707f151d6SMatthias Ringwald     uint8_t ad_data[31];
7807f151d6SMatthias Ringwald     uint8_t scan_len;
7907f151d6SMatthias Ringwald     uint8_t scan_data[31];
8007f151d6SMatthias Ringwald } device_info_t;
8107f151d6SMatthias Ringwald 
8207f151d6SMatthias Ringwald typedef struct {
8307f151d6SMatthias Ringwald     btstack_linked_item_t  item;
8407f151d6SMatthias Ringwald     hci_con_handle_t handle;
8507f151d6SMatthias Ringwald     uint8_t len;
8607f151d6SMatthias Ringwald     uint8_t data[MAX_ATT_MTU];
8707f151d6SMatthias Ringwald } att_pdu_t;
8807f151d6SMatthias Ringwald 
8907f151d6SMatthias Ringwald typedef enum {
9007f151d6SMatthias Ringwald     TC_OFF,
9107f151d6SMatthias Ringwald     TC_SCANNING,
9207f151d6SMatthias Ringwald     TC_W4_CONNECT,
9307f151d6SMatthias Ringwald     TC_CONNECTED,
9407f151d6SMatthias Ringwald } app_state_t;
9507f151d6SMatthias Ringwald 
9607f151d6SMatthias Ringwald static uint16_t devices_found;
9707f151d6SMatthias Ringwald static device_info_t devices[MAX_NUM_DEVICES];
9807f151d6SMatthias Ringwald 
9907f151d6SMatthias Ringwald static uint16_t         remote_peripheral_index;
10007f151d6SMatthias Ringwald static bd_addr_t        remote_peripheral_addr;
10107f151d6SMatthias Ringwald static bd_addr_type_t   remote_peripheral_addr_type;
10207f151d6SMatthias Ringwald static hci_con_handle_t remote_peripheral_handle;
10307f151d6SMatthias Ringwald 
10407f151d6SMatthias Ringwald static hci_con_handle_t remote_central_handle;
10507f151d6SMatthias Ringwald 
10607f151d6SMatthias Ringwald static btstack_linked_list_t outgoing_att_pdus;
10707f151d6SMatthias Ringwald 
10807f151d6SMatthias Ringwald static app_state_t state = TC_OFF;
10907f151d6SMatthias Ringwald static btstack_packet_callback_registration_t hci_event_callback_registration;
11007f151d6SMatthias Ringwald static btstack_packet_callback_registration_t sm_event_callback_registration;
11107f151d6SMatthias Ringwald 
11207f151d6SMatthias Ringwald static const char * ad_types[] = {
11307f151d6SMatthias Ringwald         "",
11407f151d6SMatthias Ringwald         "Flags",
11507f151d6SMatthias Ringwald         "Incomplete 16-bit UUIDs",
11607f151d6SMatthias Ringwald         "Complete 16-bit UUIDs",
11707f151d6SMatthias Ringwald         "Incomplete 32-bit UUIDs",
11807f151d6SMatthias Ringwald         "Complete 32-bit UUIDs",
11907f151d6SMatthias Ringwald         "Incomplete 128-bit UUIDs",
12007f151d6SMatthias Ringwald         "Complete 128-bit UUIDs",
12107f151d6SMatthias Ringwald         "Short Name",
12207f151d6SMatthias Ringwald         "Complete Name",
12307f151d6SMatthias Ringwald         "Tx Power Level",
12407f151d6SMatthias Ringwald         "",
12507f151d6SMatthias Ringwald         "",
12607f151d6SMatthias Ringwald         "Class of Device",
12707f151d6SMatthias Ringwald         "Simple Pairing Hash C",
12807f151d6SMatthias Ringwald         "Simple Pairing Randomizer R",
12907f151d6SMatthias Ringwald         "Device ID",
13007f151d6SMatthias Ringwald         "Security Manager TK Value",
13107f151d6SMatthias Ringwald         "Slave Connection Interval Range",
13207f151d6SMatthias Ringwald         "",
13307f151d6SMatthias Ringwald         "16-bit Solicitation UUIDs",
13407f151d6SMatthias Ringwald         "128-bit Solicitation UUIDs",
13507f151d6SMatthias Ringwald         "Service Data",
13607f151d6SMatthias Ringwald         "Public Target Address",
13707f151d6SMatthias Ringwald         "Random Target Address",
13807f151d6SMatthias Ringwald         "Appearance",
13907f151d6SMatthias Ringwald         "Advertising Interval"
14007f151d6SMatthias Ringwald };
14107f151d6SMatthias Ringwald 
14207f151d6SMatthias Ringwald static const char * adv_failed_warning = "\n"
14307f151d6SMatthias Ringwald  "[!] Start advertising failed!\n"
14407f151d6SMatthias Ringwald  "[!] Make sure your Bluetooth Controller supports Central and Peripheral Roles at the same time.\n\n";
14507f151d6SMatthias Ringwald 
14607f151d6SMatthias Ringwald // att pdu pool implementation
14707f151d6SMatthias Ringwald #ifndef HAVE_MALLOC
14807f151d6SMatthias Ringwald static att_pdu_t att_pdu_storage[MAX_NUM_ATT_PDUS];
14907f151d6SMatthias Ringwald static btstack_memory_pool_t att_pdu_pool;
btstack_memory_att_pdu_get(void)15007f151d6SMatthias Ringwald static att_pdu_t * btstack_memory_att_pdu_get(void){
15107f151d6SMatthias Ringwald     void * buffer = btstack_memory_pool_get(&att_pdu_pool);
15207f151d6SMatthias Ringwald     if (buffer){
15307f151d6SMatthias Ringwald         memset(buffer, 0, sizeof(att_pdu_t));
15407f151d6SMatthias Ringwald     }
15507f151d6SMatthias Ringwald     return (att_pdu_t *) buffer;
15607f151d6SMatthias Ringwald }
btstack_memory_att_pdu_free(att_pdu_t * att_pdu)15707f151d6SMatthias Ringwald static void btstack_memory_att_pdu_free(att_pdu_t *att_pdu){
15807f151d6SMatthias Ringwald     btstack_memory_pool_free(&att_pdu_pool, att_pdu);
15907f151d6SMatthias Ringwald }
16007f151d6SMatthias Ringwald #else
btstack_memory_att_pdu_get(void)16107f151d6SMatthias Ringwald static att_pdu_t * btstack_memory_att_pdu_get(void){
16207f151d6SMatthias Ringwald     void * buffer = malloc(sizeof(att_pdu_t));
16307f151d6SMatthias Ringwald     if (buffer){
16407f151d6SMatthias Ringwald         memset(buffer, 0, sizeof(att_pdu_t));
16507f151d6SMatthias Ringwald     }
16607f151d6SMatthias Ringwald     return (att_pdu_t *) buffer;
16707f151d6SMatthias Ringwald }
btstack_memory_att_pdu_free(att_pdu_t * att_pdu)16807f151d6SMatthias Ringwald static void btstack_memory_att_pdu_free(att_pdu_t * att_pdu){
16907f151d6SMatthias Ringwald     free(att_pdu);
17007f151d6SMatthias Ringwald }
17107f151d6SMatthias Ringwald #endif
17207f151d6SMatthias Ringwald 
mitm_start_scan(btstack_timer_source_t * ts)17307f151d6SMatthias Ringwald static void mitm_start_scan(btstack_timer_source_t * ts){
17407f151d6SMatthias Ringwald     UNUSED(ts);
17507f151d6SMatthias Ringwald     printf("[-] Start scanning\n");
17607f151d6SMatthias Ringwald     printf("To select device, enter advertisement number:\n");
17707f151d6SMatthias Ringwald     state = TC_SCANNING;
17807f151d6SMatthias Ringwald     gap_set_scan_parameters(0,0x0030, 0x0030);
17907f151d6SMatthias Ringwald     gap_start_scan();
18007f151d6SMatthias Ringwald }
18107f151d6SMatthias Ringwald 
mitm_connect(uint16_t index)18207f151d6SMatthias Ringwald static void mitm_connect(uint16_t index){
18307f151d6SMatthias Ringwald     // stop scanning, and connect to the device
18407f151d6SMatthias Ringwald     gap_stop_scan();
18507f151d6SMatthias Ringwald     state = TC_W4_CONNECT;
18607f151d6SMatthias Ringwald     remote_peripheral_index = index;
18707f151d6SMatthias Ringwald     memcpy(remote_peripheral_addr, devices[index].addr, 6);
18807f151d6SMatthias Ringwald     remote_peripheral_addr_type = devices[index].addr_type;
18907f151d6SMatthias Ringwald     printf("\n");
19007f151d6SMatthias Ringwald     printf("[-] Connecting to Peripheral %s\n", bd_addr_to_str(remote_peripheral_addr));
19107f151d6SMatthias Ringwald     gap_auto_connection_start(remote_peripheral_addr_type, remote_peripheral_addr);
19207f151d6SMatthias Ringwald }
19307f151d6SMatthias Ringwald 
mitm_start_advertising(void)19407f151d6SMatthias Ringwald static void mitm_start_advertising(void){
19507f151d6SMatthias Ringwald     // set adv + scan data if available
19607f151d6SMatthias Ringwald     if (devices[remote_peripheral_index].ad_len > 0){
19707f151d6SMatthias Ringwald         gap_advertisements_set_data(devices[remote_peripheral_index].ad_len, devices[remote_peripheral_index].ad_data);
19807f151d6SMatthias Ringwald         printf("[-] Setup adv data (len %02u): ", devices[remote_peripheral_index].ad_len);
19907f151d6SMatthias Ringwald         printf_hexdump(devices[remote_peripheral_index].ad_data, devices[remote_peripheral_index].ad_len);
20007f151d6SMatthias Ringwald     }
20107f151d6SMatthias Ringwald     if (devices[remote_peripheral_index].scan_len > 0){
20207f151d6SMatthias Ringwald         gap_scan_response_set_data(devices[remote_peripheral_index].scan_len, devices[remote_peripheral_index].scan_data);
20307f151d6SMatthias Ringwald         printf("[-] Setup scan data (len %02u): ", devices[remote_peripheral_index].scan_len);
20407f151d6SMatthias Ringwald         printf_hexdump(devices[remote_peripheral_index].ad_data, devices[remote_peripheral_index].ad_len);
20507f151d6SMatthias Ringwald     }
20607f151d6SMatthias Ringwald     uint16_t adv_int_min = 0x0030;
20707f151d6SMatthias Ringwald     uint16_t adv_int_max = 0x0030;
20807f151d6SMatthias Ringwald     uint8_t adv_type = 0;
20907f151d6SMatthias Ringwald     bd_addr_t null_addr;
21007f151d6SMatthias Ringwald     memset(null_addr, 0, 6);
21107f151d6SMatthias Ringwald     gap_advertisements_set_params(adv_int_min, adv_int_max, adv_type, 0, null_addr, 0x07, 0x00);
21207f151d6SMatthias Ringwald     gap_advertisements_enable(1);
21307f151d6SMatthias Ringwald }
21407f151d6SMatthias Ringwald 
mitm_print_advertisement(uint16_t index)21507f151d6SMatthias Ringwald static void mitm_print_advertisement(uint16_t index) {
21607f151d6SMatthias Ringwald     // get character for index
21707f151d6SMatthias Ringwald     char c;
21807f151d6SMatthias Ringwald     if (index < 10) {
21907f151d6SMatthias Ringwald         c = '0' + index;
22007f151d6SMatthias Ringwald     } else {
22107f151d6SMatthias Ringwald         c = 'a' + (index - 10);
22207f151d6SMatthias Ringwald     }
22307f151d6SMatthias Ringwald 
22407f151d6SMatthias Ringwald     printf("%c. %s (%-3d dBm)", c, bd_addr_to_str(devices[index].addr), devices[index].rssi);
22507f151d6SMatthias Ringwald 
22607f151d6SMatthias Ringwald     ad_context_t context;
22707f151d6SMatthias Ringwald     bd_addr_t address;
22807f151d6SMatthias Ringwald     uint8_t uuid_128[16];
22907f151d6SMatthias Ringwald     for (ad_iterator_init(&context, devices[index].ad_len, devices[index].ad_data); ad_iterator_has_more(
23007f151d6SMatthias Ringwald             &context); ad_iterator_next(&context)) {
23107f151d6SMatthias Ringwald         uint8_t data_type = ad_iterator_get_data_type(&context);
23207f151d6SMatthias Ringwald         uint8_t size = ad_iterator_get_data_len(&context);
23307f151d6SMatthias Ringwald         const uint8_t *data = ad_iterator_get_data(&context);
23407f151d6SMatthias Ringwald 
23507f151d6SMatthias Ringwald         if (data_type > 0 && data_type < 0x1B) {
23607f151d6SMatthias Ringwald             printf(" - %s: ", ad_types[data_type]);
23707f151d6SMatthias Ringwald         }
23807f151d6SMatthias Ringwald         uint8_t i;
23907f151d6SMatthias Ringwald         switch (data_type) {
24007f151d6SMatthias Ringwald             case BLUETOOTH_DATA_TYPE_FLAGS:
24107f151d6SMatthias Ringwald                 printf("0x%02x", data[0]);
24207f151d6SMatthias Ringwald                 break;
24307f151d6SMatthias Ringwald             case BLUETOOTH_DATA_TYPE_INCOMPLETE_LIST_OF_16_BIT_SERVICE_CLASS_UUIDS:
24407f151d6SMatthias Ringwald             case BLUETOOTH_DATA_TYPE_COMPLETE_LIST_OF_16_BIT_SERVICE_CLASS_UUIDS:
24507f151d6SMatthias Ringwald             case BLUETOOTH_DATA_TYPE_LIST_OF_16_BIT_SERVICE_SOLICITATION_UUIDS:
24607f151d6SMatthias Ringwald                 for (i = 0; i < size; i += 2) {
24707f151d6SMatthias Ringwald                     printf("%02X ", little_endian_read_16(data, i));
24807f151d6SMatthias Ringwald                 }
24907f151d6SMatthias Ringwald                 break;
25007f151d6SMatthias Ringwald             case BLUETOOTH_DATA_TYPE_INCOMPLETE_LIST_OF_32_BIT_SERVICE_CLASS_UUIDS:
25107f151d6SMatthias Ringwald             case BLUETOOTH_DATA_TYPE_COMPLETE_LIST_OF_32_BIT_SERVICE_CLASS_UUIDS:
25207f151d6SMatthias Ringwald             case BLUETOOTH_DATA_TYPE_LIST_OF_32_BIT_SERVICE_SOLICITATION_UUIDS:
25307f151d6SMatthias Ringwald                 for (i = 0; i < size; i += 4) {
25407f151d6SMatthias Ringwald                     printf("%04"PRIX32, little_endian_read_32(data, i));
25507f151d6SMatthias Ringwald                 }
25607f151d6SMatthias Ringwald                 break;
25707f151d6SMatthias Ringwald             case BLUETOOTH_DATA_TYPE_INCOMPLETE_LIST_OF_128_BIT_SERVICE_CLASS_UUIDS:
25807f151d6SMatthias Ringwald             case BLUETOOTH_DATA_TYPE_COMPLETE_LIST_OF_128_BIT_SERVICE_CLASS_UUIDS:
25907f151d6SMatthias Ringwald             case BLUETOOTH_DATA_TYPE_LIST_OF_128_BIT_SERVICE_SOLICITATION_UUIDS:
26007f151d6SMatthias Ringwald                 reverse_128(data, uuid_128);
26107f151d6SMatthias Ringwald                 printf("%s", uuid128_to_str(uuid_128));
26207f151d6SMatthias Ringwald                 break;
26307f151d6SMatthias Ringwald             case BLUETOOTH_DATA_TYPE_SHORTENED_LOCAL_NAME:
26407f151d6SMatthias Ringwald             case BLUETOOTH_DATA_TYPE_COMPLETE_LOCAL_NAME:
26507f151d6SMatthias Ringwald                 for (i = 0; i < size; i++) {
26607f151d6SMatthias Ringwald                     printf("%c", (char) (data[i]));
26707f151d6SMatthias Ringwald                 }
26807f151d6SMatthias Ringwald                 break;
26907f151d6SMatthias Ringwald             case BLUETOOTH_DATA_TYPE_TX_POWER_LEVEL:
27007f151d6SMatthias Ringwald                 printf("%d dBm", *(int8_t *) data);
27107f151d6SMatthias Ringwald                 break;
27207f151d6SMatthias Ringwald             case BLUETOOTH_DATA_TYPE_SLAVE_CONNECTION_INTERVAL_RANGE:
27307f151d6SMatthias Ringwald                 printf("Connection Interval Min = %u ms, Max = %u ms", little_endian_read_16(data, 0) * 5 / 4,
27407f151d6SMatthias Ringwald                        little_endian_read_16(data, 2) * 5 / 4);
27507f151d6SMatthias Ringwald                 break;
27607f151d6SMatthias Ringwald             case BLUETOOTH_DATA_TYPE_SERVICE_DATA:
27707f151d6SMatthias Ringwald                 printf_hexdump(data, size);
27807f151d6SMatthias Ringwald                 break;
27907f151d6SMatthias Ringwald             case BLUETOOTH_DATA_TYPE_PUBLIC_TARGET_ADDRESS:
28007f151d6SMatthias Ringwald             case BLUETOOTH_DATA_TYPE_RANDOM_TARGET_ADDRESS:
28107f151d6SMatthias Ringwald                 reverse_bd_addr(data, address);
28207f151d6SMatthias Ringwald                 printf("%s", bd_addr_to_str(address));
28307f151d6SMatthias Ringwald                 break;
28407f151d6SMatthias Ringwald             case BLUETOOTH_DATA_TYPE_APPEARANCE:
28507f151d6SMatthias Ringwald                 // https://developer.bluetooth.org/gatt/characteristics/Pages/CharacteristicViewer.aspx?u=org.bluetooth.characteristic.gap.appearance.xml
28607f151d6SMatthias Ringwald                 printf("%02X", little_endian_read_16(data, 0));
28707f151d6SMatthias Ringwald                 break;
28807f151d6SMatthias Ringwald             case BLUETOOTH_DATA_TYPE_ADVERTISING_INTERVAL:
28907f151d6SMatthias Ringwald                 printf("%u ms", little_endian_read_16(data, 0) * 5 / 8);
29007f151d6SMatthias Ringwald                 break;
29107f151d6SMatthias Ringwald             case BLUETOOTH_DATA_TYPE_3D_INFORMATION_DATA:
29207f151d6SMatthias Ringwald                 printf_hexdump(data, size);
29307f151d6SMatthias Ringwald                 break;
29407f151d6SMatthias Ringwald             case BLUETOOTH_DATA_TYPE_MANUFACTURER_SPECIFIC_DATA:
29507f151d6SMatthias Ringwald             case BLUETOOTH_DATA_TYPE_CLASS_OF_DEVICE:
29607f151d6SMatthias Ringwald             case BLUETOOTH_DATA_TYPE_SIMPLE_PAIRING_HASH_C:
29707f151d6SMatthias Ringwald             case BLUETOOTH_DATA_TYPE_SIMPLE_PAIRING_RANDOMIZER_R:
29807f151d6SMatthias Ringwald             case BLUETOOTH_DATA_TYPE_DEVICE_ID:
29907f151d6SMatthias Ringwald             case BLUETOOTH_DATA_TYPE_SECURITY_MANAGER_OUT_OF_BAND_FLAGS:
30007f151d6SMatthias Ringwald             default:
30107f151d6SMatthias Ringwald                 break;
30207f151d6SMatthias Ringwald         }
30307f151d6SMatthias Ringwald     }
30407f151d6SMatthias Ringwald     printf("\n");
30507f151d6SMatthias Ringwald }
30607f151d6SMatthias Ringwald 
mitm_handle_adv(uint8_t * packet)30707f151d6SMatthias Ringwald static void mitm_handle_adv(uint8_t * packet){
30807f151d6SMatthias Ringwald     // get addr and type
30907f151d6SMatthias Ringwald     bd_addr_t remote_addr;
31007f151d6SMatthias Ringwald     gap_event_advertising_report_get_address(packet, remote_addr);
31107f151d6SMatthias Ringwald     bd_addr_type_t remote_addr_type = gap_event_advertising_report_get_address_type(packet);
31207f151d6SMatthias Ringwald     uint8_t adv_event_type = gap_event_advertising_report_get_advertising_event_type(packet);
31307f151d6SMatthias Ringwald     bool is_scan_response = adv_event_type == 2 || adv_event_type == 4;
31407f151d6SMatthias Ringwald 
31507f151d6SMatthias Ringwald     // find remote in list
31607f151d6SMatthias Ringwald     uint16_t i;
31707f151d6SMatthias Ringwald     for (i=0;i<devices_found;i++) {
31807f151d6SMatthias Ringwald         if (memcmp(remote_addr, devices[i].addr, 6) != 0) continue;
31907f151d6SMatthias Ringwald         if (remote_addr_type != devices[i].addr_type) continue;
32007f151d6SMatthias Ringwald         break;
32107f151d6SMatthias Ringwald     }
32207f151d6SMatthias Ringwald 
32307f151d6SMatthias Ringwald     if (i == MAX_NUM_DEVICES) return;
32407f151d6SMatthias Ringwald 
32507f151d6SMatthias Ringwald     if (devices_found == i){
32607f151d6SMatthias Ringwald         // skip first event with scan response data (should not happen)
32707f151d6SMatthias Ringwald         if (is_scan_response) return;
32807f151d6SMatthias Ringwald         memset(&devices[i], 0, sizeof(device_info_t));
32907f151d6SMatthias Ringwald         devices[i].rssi = (int8_t) gap_event_advertising_report_get_rssi(packet);
33007f151d6SMatthias Ringwald         devices[i].addr_type = remote_addr_type;
33107f151d6SMatthias Ringwald         memcpy(devices[i].addr, remote_addr, 6);
33207f151d6SMatthias Ringwald         devices[i].ad_len = gap_event_advertising_report_get_data_length(packet);
33307f151d6SMatthias Ringwald         memcpy(devices[i].ad_data, gap_event_advertising_report_get_data(packet), devices[i].ad_len);
33407f151d6SMatthias Ringwald         mitm_print_advertisement(i);
33507f151d6SMatthias Ringwald         devices_found++;
33607f151d6SMatthias Ringwald         return;
33707f151d6SMatthias Ringwald     }
33807f151d6SMatthias Ringwald 
33907f151d6SMatthias Ringwald     // store scan data
34007f151d6SMatthias Ringwald     if (!is_scan_response) return;
34107f151d6SMatthias Ringwald     devices[i].scan_len = gap_event_advertising_report_get_data_length(packet);
34207f151d6SMatthias Ringwald     memcpy(devices[i].scan_data, gap_event_advertising_report_get_data(packet), devices[i].scan_len);
34307f151d6SMatthias Ringwald }
34407f151d6SMatthias Ringwald 
mitm_console_connected_menu(void)34507f151d6SMatthias Ringwald static void mitm_console_connected_menu(void){
34607f151d6SMatthias Ringwald     printf("=== Connected menu ===\n");
34707f151d6SMatthias Ringwald     printf("p - Pair Peripheral\n");
34807f151d6SMatthias Ringwald }
34907f151d6SMatthias Ringwald 
mitm_opposite_handle(hci_con_handle_t handle)35007f151d6SMatthias Ringwald static hci_con_handle_t mitm_opposite_handle(hci_con_handle_t handle){
35107f151d6SMatthias Ringwald     if (handle == remote_peripheral_handle) {
35207f151d6SMatthias Ringwald         return remote_central_handle;
35307f151d6SMatthias Ringwald     } else {
35407f151d6SMatthias Ringwald         return remote_peripheral_handle;
35507f151d6SMatthias Ringwald     }
35607f151d6SMatthias Ringwald }
35707f151d6SMatthias Ringwald 
mitm_request_to_send(void)35807f151d6SMatthias Ringwald static void mitm_request_to_send(void){
35907f151d6SMatthias Ringwald     // request to send again if more packets queued
36007f151d6SMatthias Ringwald     if (btstack_linked_list_empty(&outgoing_att_pdus)) return;
36107f151d6SMatthias Ringwald     att_pdu_t * pdu = (att_pdu_t *) btstack_linked_list_get_first_item((&outgoing_att_pdus));
36207f151d6SMatthias Ringwald     l2cap_request_can_send_fix_channel_now_event(pdu->handle, L2CAP_CID_ATTRIBUTE_PROTOCOL);
36307f151d6SMatthias Ringwald }
36407f151d6SMatthias Ringwald 
mitm_name_for_handle(hci_con_handle_t handle)36507f151d6SMatthias Ringwald static const char * mitm_name_for_handle(hci_con_handle_t handle){
36607f151d6SMatthias Ringwald     if (handle == remote_peripheral_handle) return "Peripheral";
36707f151d6SMatthias Ringwald     if (handle == remote_central_handle)    return "Central";
36807f151d6SMatthias Ringwald     return "(unknown handle)'";
36907f151d6SMatthias Ringwald }
37007f151d6SMatthias Ringwald 
hci_event_handler(uint8_t packet_type,uint16_t channel,uint8_t * packet,uint16_t size)37107f151d6SMatthias Ringwald static void hci_event_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
37207f151d6SMatthias Ringwald     UNUSED(channel);
37307f151d6SMatthias Ringwald     UNUSED(size);
37407f151d6SMatthias Ringwald 
37507f151d6SMatthias Ringwald     if (packet_type != HCI_EVENT_PACKET) return;
37607f151d6SMatthias Ringwald 
37707f151d6SMatthias Ringwald     uint8_t event = hci_event_packet_get_type(packet);
37807f151d6SMatthias Ringwald     hci_con_handle_t connection_handle;
37907f151d6SMatthias Ringwald     uint32_t passkey;
38007f151d6SMatthias Ringwald 
38107f151d6SMatthias Ringwald     switch (event) {
38207f151d6SMatthias Ringwald         case BTSTACK_EVENT_STATE:
38307f151d6SMatthias Ringwald             // BTstack activated, get started
38407f151d6SMatthias Ringwald             if (btstack_event_state_get_state(packet) == HCI_STATE_WORKING) {
38507f151d6SMatthias Ringwald                 mitm_start_scan(NULL);
38607f151d6SMatthias Ringwald                 state = TC_SCANNING;
38707f151d6SMatthias Ringwald             } else {
38807f151d6SMatthias Ringwald                 state = TC_OFF;
38907f151d6SMatthias Ringwald             }
39007f151d6SMatthias Ringwald             break;
39107f151d6SMatthias Ringwald         case GAP_EVENT_ADVERTISING_REPORT:
39207f151d6SMatthias Ringwald             if (state != TC_SCANNING) return;
39307f151d6SMatthias Ringwald             mitm_handle_adv(packet);
39407f151d6SMatthias Ringwald             break;
39507f151d6SMatthias Ringwald         case HCI_EVENT_COMMAND_COMPLETE:
39607f151d6SMatthias Ringwald             // warn if adv enable fails
39707f151d6SMatthias Ringwald             if (hci_event_command_complete_get_command_opcode(packet) != hci_le_set_advertise_enable.opcode) break;
39807f151d6SMatthias Ringwald             if (hci_event_command_complete_get_return_parameters(packet)[0] == ERROR_CODE_SUCCESS) break;
39907f151d6SMatthias Ringwald             printf("%s", adv_failed_warning);
40007f151d6SMatthias Ringwald             break;
401*bba48196SMatthias Ringwald         case HCI_EVENT_META_GAP:
40207f151d6SMatthias Ringwald             // wait for connection complete
403*bba48196SMatthias Ringwald             if (hci_event_gap_meta_get_subevent_code(packet) !=  GAP_SUBEVENT_LE_CONNECTION_COMPLETE) break;
40407f151d6SMatthias Ringwald             switch (state){
40507f151d6SMatthias Ringwald                 case TC_W4_CONNECT:
40607f151d6SMatthias Ringwald                     state = TC_CONNECTED;
407*bba48196SMatthias Ringwald                     remote_peripheral_handle = gap_subevent_le_connection_complete_get_connection_handle(packet);
40807f151d6SMatthias Ringwald                     printf("[-] Peripheral connected\n");
40907f151d6SMatthias Ringwald                     mitm_start_advertising();
41007f151d6SMatthias Ringwald                     printf ("You can connect now!\n");
41107f151d6SMatthias Ringwald                     printf("\n");
41207f151d6SMatthias Ringwald                     mitm_console_connected_menu();
41307f151d6SMatthias Ringwald                     break;
41407f151d6SMatthias Ringwald                 case TC_CONNECTED:
415*bba48196SMatthias Ringwald                     remote_central_handle = gap_subevent_le_connection_complete_get_connection_handle(packet);
41607f151d6SMatthias Ringwald                     printf("[-] Central connected!\n");
41707f151d6SMatthias Ringwald                     break;
41807f151d6SMatthias Ringwald                 default:
41907f151d6SMatthias Ringwald                     break;
42007f151d6SMatthias Ringwald             }
42107f151d6SMatthias Ringwald             break;
42207f151d6SMatthias Ringwald         case HCI_EVENT_DISCONNECTION_COMPLETE:
42307f151d6SMatthias Ringwald             // unregister listener
42407f151d6SMatthias Ringwald             connection_handle = HCI_CON_HANDLE_INVALID;
42507f151d6SMatthias Ringwald             printf("[-] %s disconnected", mitm_name_for_handle(connection_handle));
42607f151d6SMatthias Ringwald             if (connection_handle == remote_peripheral_handle){
42707f151d6SMatthias Ringwald                 mitm_start_scan(NULL);
42807f151d6SMatthias Ringwald                 state = TC_SCANNING;
42907f151d6SMatthias Ringwald             }
43007f151d6SMatthias Ringwald             break;
43107f151d6SMatthias Ringwald         case SM_EVENT_JUST_WORKS_REQUEST:
43207f151d6SMatthias Ringwald             connection_handle = sm_event_just_works_request_get_handle(packet);
43307f151d6SMatthias Ringwald             printf("[-] %s request 'Just Works' pairing\n", mitm_name_for_handle(connection_handle));
43407f151d6SMatthias Ringwald             sm_just_works_confirm(connection_handle);
43507f151d6SMatthias Ringwald             break;
43607f151d6SMatthias Ringwald         case SM_EVENT_NUMERIC_COMPARISON_REQUEST:
43707f151d6SMatthias Ringwald             passkey = sm_event_numeric_comparison_request_get_passkey(packet);
43807f151d6SMatthias Ringwald             connection_handle = sm_event_numeric_comparison_request_get_handle(packet);
43907f151d6SMatthias Ringwald             printf("[-] %s accepting numeric comparison: %"PRIu32"\n", mitm_name_for_handle(connection_handle), passkey);
44007f151d6SMatthias Ringwald             sm_numeric_comparison_confirm(connection_handle);
44107f151d6SMatthias Ringwald             break;
44207f151d6SMatthias Ringwald         case SM_EVENT_PASSKEY_DISPLAY_NUMBER:
44307f151d6SMatthias Ringwald             passkey = sm_event_passkey_display_number_get_passkey(packet);
44407f151d6SMatthias Ringwald             connection_handle = sm_event_passkey_display_number_get_handle(packet);
44507f151d6SMatthias Ringwald             printf("[-] %s display passkey: %"PRIu32"\n", mitm_name_for_handle(connection_handle), passkey);
44607f151d6SMatthias Ringwald             break;
44707f151d6SMatthias Ringwald         case SM_EVENT_PAIRING_COMPLETE:
44807f151d6SMatthias Ringwald             connection_handle = sm_event_pairing_complete_get_handle(packet);
44907f151d6SMatthias Ringwald             switch (sm_event_pairing_complete_get_status(packet)){
45007f151d6SMatthias Ringwald                 case ERROR_CODE_SUCCESS:
45107f151d6SMatthias Ringwald                     printf("[-] %s pairing complete, success\n", mitm_name_for_handle(connection_handle));
45207f151d6SMatthias Ringwald                     break;
45307f151d6SMatthias Ringwald                 case ERROR_CODE_CONNECTION_TIMEOUT:
45407f151d6SMatthias Ringwald                     printf("[-] %s pairing failed, timeout\n", mitm_name_for_handle(connection_handle));
45507f151d6SMatthias Ringwald                     break;
45607f151d6SMatthias Ringwald                 case ERROR_CODE_REMOTE_USER_TERMINATED_CONNECTION:
45707f151d6SMatthias Ringwald                     printf("[-] %s pairing failed, disconnected\n", mitm_name_for_handle(connection_handle));
45807f151d6SMatthias Ringwald                     break;
45907f151d6SMatthias Ringwald                 case ERROR_CODE_AUTHENTICATION_FAILURE:
46007f151d6SMatthias Ringwald                     printf("[-] %s pairing failed, reason = %u\n", mitm_name_for_handle(connection_handle), sm_event_pairing_complete_get_reason(packet));
46107f151d6SMatthias Ringwald                     break;
46207f151d6SMatthias Ringwald                 default:
46307f151d6SMatthias Ringwald                     break;
46407f151d6SMatthias Ringwald             }
46507f151d6SMatthias Ringwald             break;
4663f6e1c81SMatthias Ringwald         case SM_EVENT_REENCRYPTION_COMPLETE:
4673f6e1c81SMatthias Ringwald             connection_handle = sm_event_reencryption_complete_get_handle(packet);
4683f6e1c81SMatthias Ringwald             printf("[-] %s Re-encryption complete, success\n", mitm_name_for_handle(connection_handle));
4693f6e1c81SMatthias Ringwald             break;
47007f151d6SMatthias Ringwald         default:
47107f151d6SMatthias Ringwald             break;
47207f151d6SMatthias Ringwald     }
47307f151d6SMatthias Ringwald }
47407f151d6SMatthias Ringwald 
att_packet_handler(uint8_t packet_type,uint16_t handle,uint8_t * packet,uint16_t size)47507f151d6SMatthias Ringwald static void att_packet_handler(uint8_t packet_type, uint16_t handle, uint8_t *packet, uint16_t size){
47607f151d6SMatthias Ringwald     att_pdu_t * pdu;
47707f151d6SMatthias Ringwald     switch (packet_type){
47807f151d6SMatthias Ringwald         case ATT_DATA_PACKET:
47907f151d6SMatthias Ringwald             printf("[%10s] ", mitm_name_for_handle(handle));
48007f151d6SMatthias Ringwald             printf_hexdump(packet, size);
48107f151d6SMatthias Ringwald             pdu = btstack_memory_att_pdu_get();
48207f151d6SMatthias Ringwald             if (!pdu) break;
48307f151d6SMatthias Ringwald             // handle att mtu exchange directly
48407f151d6SMatthias Ringwald             if (packet[0] == ATT_EXCHANGE_MTU_REQUEST){
48507f151d6SMatthias Ringwald                 pdu->handle = handle;
48607f151d6SMatthias Ringwald                 pdu->len = 3;
48707f151d6SMatthias Ringwald                 pdu->data[0] = ATT_EXCHANGE_MTU_RESPONSE;
48807f151d6SMatthias Ringwald                 little_endian_store_16(pdu->data, 1, MAX_ATT_MTU);
48907f151d6SMatthias Ringwald             } else {
49007f151d6SMatthias Ringwald                 btstack_assert(size <= MAX_ATT_MTU);
49107f151d6SMatthias Ringwald                 pdu->handle = mitm_opposite_handle(handle);
4920801ef92SMatthias Ringwald                 pdu->len = (uint8_t) size;
49307f151d6SMatthias Ringwald                 memcpy(pdu->data, packet, size);
49407f151d6SMatthias Ringwald             }
49507f151d6SMatthias Ringwald             btstack_linked_list_add_tail(&outgoing_att_pdus, (btstack_linked_item_t *) pdu);
49607f151d6SMatthias Ringwald             mitm_request_to_send();
49707f151d6SMatthias Ringwald             break;
49807f151d6SMatthias Ringwald         case HCI_EVENT_PACKET:
49907f151d6SMatthias Ringwald             if (packet[0] == L2CAP_EVENT_CAN_SEND_NOW) {
50007f151d6SMatthias Ringwald                 // send next packet
50107f151d6SMatthias Ringwald                 pdu = (att_pdu_t *) btstack_linked_list_pop(&outgoing_att_pdus);
50207f151d6SMatthias Ringwald                 if (pdu == NULL) break;
50307f151d6SMatthias Ringwald                 l2cap_send_connectionless(pdu->handle, L2CAP_CID_ATTRIBUTE_PROTOCOL, pdu->data, pdu->len);
50407f151d6SMatthias Ringwald                 btstack_memory_att_pdu_free(pdu);
50507f151d6SMatthias Ringwald                 // request to send again if more packets queued
50607f151d6SMatthias Ringwald                 mitm_request_to_send();
50707f151d6SMatthias Ringwald             }
50807f151d6SMatthias Ringwald             break;
50907f151d6SMatthias Ringwald         default:
51007f151d6SMatthias Ringwald             break;
51107f151d6SMatthias Ringwald     }
51207f151d6SMatthias Ringwald }
51307f151d6SMatthias Ringwald 
stdin_process(char cmd)51407f151d6SMatthias Ringwald static void stdin_process(char cmd) {
51507f151d6SMatthias Ringwald     unsigned int index;
51607f151d6SMatthias Ringwald     switch(state){
51707f151d6SMatthias Ringwald         case TC_OFF:
51807f151d6SMatthias Ringwald             break;
51907f151d6SMatthias Ringwald         case TC_SCANNING:
52007f151d6SMatthias Ringwald             if ((cmd >= '0') && (cmd <= '9')){
52107f151d6SMatthias Ringwald                 index = cmd - '0';
52207f151d6SMatthias Ringwald             } else if ((cmd >= 'a') && (cmd <= 'z')){
52307f151d6SMatthias Ringwald                 index = cmd - 'a' + 10;
52407f151d6SMatthias Ringwald             } else {
52507f151d6SMatthias Ringwald                 break;
52607f151d6SMatthias Ringwald             }
52707f151d6SMatthias Ringwald             if (index >= devices_found) break;
52807f151d6SMatthias Ringwald             mitm_connect(index);
52907f151d6SMatthias Ringwald             break;
53007f151d6SMatthias Ringwald         case TC_CONNECTED:
53107f151d6SMatthias Ringwald             switch (cmd){
53207f151d6SMatthias Ringwald                 case 'p':
53307f151d6SMatthias Ringwald                     printf("[-] Start pairing / encryption with Peripheral\n");
53407f151d6SMatthias Ringwald                     sm_request_pairing(remote_peripheral_handle);
53507f151d6SMatthias Ringwald                     break;
53607f151d6SMatthias Ringwald                 default:
53707f151d6SMatthias Ringwald                     mitm_console_connected_menu();
53807f151d6SMatthias Ringwald                     break;
53907f151d6SMatthias Ringwald             }
54007f151d6SMatthias Ringwald             break;
54107f151d6SMatthias Ringwald         default:
54207f151d6SMatthias Ringwald             break;
54307f151d6SMatthias Ringwald     }
54407f151d6SMatthias Ringwald }
54507f151d6SMatthias Ringwald 
54607f151d6SMatthias Ringwald int btstack_main(int argc, const char * argv[]);
btstack_main(int argc,const char * argv[])54707f151d6SMatthias Ringwald int btstack_main(int argc, const char * argv[]){
54807f151d6SMatthias Ringwald 
54907f151d6SMatthias Ringwald     (void)argc;
55007f151d6SMatthias Ringwald     (void)argv;
55107f151d6SMatthias Ringwald 
55207f151d6SMatthias Ringwald     l2cap_init();
55307f151d6SMatthias Ringwald 
55407f151d6SMatthias Ringwald     l2cap_register_fixed_channel(att_packet_handler, L2CAP_CID_ATTRIBUTE_PROTOCOL);
55507f151d6SMatthias Ringwald 
55607f151d6SMatthias Ringwald     sm_init();
55707f151d6SMatthias Ringwald 
55807f151d6SMatthias Ringwald     hci_event_callback_registration.callback = &hci_event_handler;
55907f151d6SMatthias Ringwald     hci_add_event_handler(&hci_event_callback_registration);
56007f151d6SMatthias Ringwald 
56107f151d6SMatthias Ringwald     sm_event_callback_registration.callback = &hci_event_handler;
56207f151d6SMatthias Ringwald     sm_add_event_handler(&sm_event_callback_registration);
56307f151d6SMatthias Ringwald 
56407f151d6SMatthias Ringwald #ifndef HAVE_MALLOC
56507f151d6SMatthias Ringwald     btstack_memory_pool_create(&att_pdu_pool, att_pdu_storage, MAX_NUM_ATT_PDUS, sizeof(att_pdu_t));
56607f151d6SMatthias Ringwald #endif
56707f151d6SMatthias Ringwald 
56807f151d6SMatthias Ringwald #ifdef HAVE_BTSTACK_STDIN
56907f151d6SMatthias Ringwald     btstack_stdin_setup(stdin_process);
57007f151d6SMatthias Ringwald #endif
57107f151d6SMatthias Ringwald 
57207f151d6SMatthias Ringwald     // turn on!
57307f151d6SMatthias Ringwald     hci_power_control(HCI_POWER_ON);
57407f151d6SMatthias Ringwald 
57507f151d6SMatthias Ringwald     return 0;
57607f151d6SMatthias Ringwald }
57707f151d6SMatthias Ringwald /* EXAMPLE_END */
578