summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar Matthias Ringwald2022-01-10 23:47:47 +0100
committerGravatar Nikias Bassen2022-05-05 19:04:56 +0200
commitbe6eca8654f9bc7c686840a85a576b6453ad012d (patch)
treee54c88dffa86e2b041cf4f5b74a275e97e70fc20
parent5b611c495910155e2c30333761adec0793313ab4 (diff)
downloadlibimobiledevice-be6eca8654f9bc7c686840a85a576b6453ad012d.tar.gz
libimobiledevice-be6eca8654f9bc7c686840a85a576b6453ad012d.tar.bz2
idevicebtlogger: add --format option for 'pcap' and 'packetlogger'
-rw-r--r--docs/idevicebtlogger.114
-rw-r--r--tools/idevicebtlogger.c106
2 files changed, 106 insertions, 14 deletions
diff --git a/docs/idevicebtlogger.1 b/docs/idevicebtlogger.1
index 24903b5..39ffff7 100644
--- a/docs/idevicebtlogger.1
+++ b/docs/idevicebtlogger.1
@@ -8,7 +8,9 @@ idevicebtlogger \- Capture HCI traffic of a connected device.
8 8
9.SH DESCRIPTION 9.SH DESCRIPTION
10 10
11Capture HCI traffic of a connected device. Requires Bluetooth logging profile to be installed on device. 11Capture HCI traffic of a connected device. Requires Bluetooth logging profile to be installed on device with iOS 13 or higher. See https://www.bluetooth.com/blog/a-new-way-to-debug-iosbluetooth-applications/ for iOS device configuration.
12
13The HCI traffic can be stored in Apple's native PacketLogger format or converted into PCAP format for live feedback in Wireshark.
12 14
13.SH OPTIONS 15.SH OPTIONS
14.TP 16.TP
@@ -18,6 +20,9 @@ target specific device by UDID
18.B \-n, \-\-network 20.B \-n, \-\-network
19connect to network device 21connect to network device
20.TP 22.TP
23.B \-f, \-\-format FORMAT
24set log format: PacketLoggger (default), or pcap
25.TP
21.B \-x, \-\-exit 26.B \-x, \-\-exit
22exit when device disconnects 27exit when device disconnects
23.TP 28.TP
@@ -37,9 +42,16 @@ Capture HCI traffic of device with UDID 00008030-0000111ABC000DEF.
37.TP 42.TP
38.B idevicebtlogger \-x 43.B idevicebtlogger \-x
39Capture HCI traffic of device and exit when the device is unplugged. 44Capture HCI traffic of device and exit when the device is unplugged.
45.TP
46.B idevicebtlogger \-f pcap
47Capture HCI traffic of device in PCAP format.
48.TP
49.B idevicebtlogger -f pcap - | wireshark -k -i -
50Capture HCI traffic and pipe it into Wireshark for live feedback.
40 51
41.SH AUTHORS 52.SH AUTHORS
42Geoffrey Kruse 53Geoffrey Kruse
54Matthias Ringwald
43 55
44.SH ON THE WEB 56.SH ON THE WEB
45https://libimobiledevice.org 57https://libimobiledevice.org
diff --git a/tools/idevicebtlogger.c b/tools/idevicebtlogger.c
index b73d958..c780143 100644
--- a/tools/idevicebtlogger.c
+++ b/tools/idevicebtlogger.c
@@ -32,6 +32,8 @@
32#include <stdlib.h> 32#include <stdlib.h>
33#include <unistd.h> 33#include <unistd.h>
34#include <getopt.h> 34#include <getopt.h>
35#include <assert.h>
36#include <fcntl.h>
35 37
36#ifdef WIN32 38#ifdef WIN32
37#include <windows.h> 39#include <windows.h>
@@ -57,7 +59,14 @@ static idevice_t device = NULL;
57static bt_packet_logger_client_t bt_packet_logger = NULL; 59static bt_packet_logger_client_t bt_packet_logger = NULL;
58static int use_network = 0; 60static int use_network = 0;
59static char* out_filename = NULL; 61static char* out_filename = NULL;
60static pcap_dumper_t * dump; 62static char* log_format_string = NULL;
63static pcap_dumper_t * pcap_dumper = NULL;
64static int packetlogger_fd = -1;
65
66static enum {
67 LOG_FORMAT_PACKETLOGGER,
68 LOG_FORMAT_PCAP
69} log_format = LOG_FORMAT_PACKETLOGGER;
61 70
62typedef enum { 71typedef enum {
63 HCI_COMMAND = 0x00, 72 HCI_COMMAND = 0x00,
@@ -67,9 +76,17 @@ typedef enum {
67} PacketLoggerPacketType; 76} PacketLoggerPacketType;
68 77
69/** 78/**
79 * Callback from the packet logger service to handle packets and log to PacketLoggger format
80 */
81static void bt_packet_logger_callback_packetlogger(uint8_t * data, uint16_t len, void *user_data)
82{
83 write(packetlogger_fd, data, len);
84}
85
86/**
70 * Callback from the packet logger service to handle packets and log to pcap 87 * Callback from the packet logger service to handle packets and log to pcap
71 */ 88 */
72static void bt_packet_logger_callback(uint8_t * data, uint16_t len, void *user_data) 89static void bt_packet_logger_callback_pcap(uint8_t * data, uint16_t len, void *user_data)
73{ 90{
74 bt_packet_logger_header_t * header = (bt_packet_logger_header_t *)data; 91 bt_packet_logger_header_t * header = (bt_packet_logger_header_t *)data;
75 uint16_t offset = sizeof(bt_packet_logger_header_t); 92 uint16_t offset = sizeof(bt_packet_logger_header_t);
@@ -126,8 +143,8 @@ static void bt_packet_logger_callback(uint8_t * data, uint16_t len, void *user_d
126 // having to memcpy things around. 143 // having to memcpy things around.
127 offset -= sizeof(uint32_t); 144 offset -= sizeof(uint32_t);
128 *(uint32_t*)&data[offset] = direction; 145 *(uint32_t*)&data[offset] = direction;
129 pcap_dump((unsigned char*)dump, &pcap_header, &data[offset]); 146 pcap_dump((unsigned char*)pcap_dumper, &pcap_header, &data[offset]);
130 pcap_dump_flush(dump); 147 pcap_dump_flush(pcap_dumper);
131 } 148 }
132} 149}
133 150
@@ -173,7 +190,19 @@ static int start_logging(void)
173 bt_packet_logger_client_start_service(device, &bt_packet_logger, TOOL_NAME); 190 bt_packet_logger_client_start_service(device, &bt_packet_logger, TOOL_NAME);
174 191
175 /* start capturing bt_packet_logger */ 192 /* start capturing bt_packet_logger */
176 bt_packet_logger_error_t serr = bt_packet_logger_start_capture(bt_packet_logger, bt_packet_logger_callback, NULL); 193 void (*callback)(uint8_t * data, uint16_t len, void *user_data);
194 switch (log_format){
195 case LOG_FORMAT_PCAP:
196 callback = bt_packet_logger_callback_pcap;
197 break;
198 case LOG_FORMAT_PACKETLOGGER:
199 callback = bt_packet_logger_callback_packetlogger;
200 break;
201 default:
202 assert(0);
203 return 0;
204 }
205 bt_packet_logger_error_t serr = bt_packet_logger_start_capture(bt_packet_logger, callback, NULL);
177 if (serr != BT_PACKET_LOGGER_E_SUCCESS) { 206 if (serr != BT_PACKET_LOGGER_E_SUCCESS) {
178 fprintf(stderr, "ERROR: Unable to start capturing bt_packet_logger.\n"); 207 fprintf(stderr, "ERROR: Unable to start capturing bt_packet_logger.\n");
179 bt_packet_logger_client_free(bt_packet_logger); 208 bt_packet_logger_client_free(bt_packet_logger);
@@ -243,12 +272,13 @@ static void print_usage(int argc, char **argv, int is_error)
243 "Capture HCI packets from a connected device.\n" \ 272 "Capture HCI packets from a connected device.\n" \
244 "\n" \ 273 "\n" \
245 "OPTIONS:\n" \ 274 "OPTIONS:\n" \
246 " -u, --udid UDID target specific device by UDID\n" \ 275 " -u, --udid UDID target specific device by UDID\n" \
247 " -n, --network connect to network device\n" \ 276 " -n, --network connect to network device\n" \
248 " -x, --exit exit when device disconnects\n" \ 277 " -f, --format FORMAT logging format: packetlogger (default) or pcap\n" \
249 " -h, --help prints usage information\n" \ 278 " -x, --exit exit when device disconnects\n" \
250 " -d, --debug enable communication debugging\n" \ 279 " -h, --help prints usage information\n" \
251 " -v, --version prints version information\n" \ 280 " -d, --debug enable communication debugging\n" \
281 " -v, --version prints version information\n" \
252 "\n" \ 282 "\n" \
253 "Homepage: <" PACKAGE_URL ">\n" 283 "Homepage: <" PACKAGE_URL ">\n"
254 "Bug Reports: <" PACKAGE_BUGREPORT ">\n" 284 "Bug Reports: <" PACKAGE_BUGREPORT ">\n"
@@ -265,6 +295,7 @@ int main(int argc, char *argv[])
265 { "debug", no_argument, NULL, 'd' }, 295 { "debug", no_argument, NULL, 'd' },
266 { "help", no_argument, NULL, 'h' }, 296 { "help", no_argument, NULL, 'h' },
267 { "udid", required_argument, NULL, 'u' }, 297 { "udid", required_argument, NULL, 'u' },
298 { "format", required_argument, NULL, 'f' },
268 { "network", no_argument, NULL, 'n' }, 299 { "network", no_argument, NULL, 'n' },
269 { "exit", no_argument, NULL, 'x' }, 300 { "exit", no_argument, NULL, 'x' },
270 { "version", no_argument, NULL, 'v' }, 301 { "version", no_argument, NULL, 'v' },
@@ -278,7 +309,7 @@ int main(int argc, char *argv[])
278 signal(SIGPIPE, SIG_IGN); 309 signal(SIGPIPE, SIG_IGN);
279#endif 310#endif
280 311
281 while ((c = getopt_long(argc, argv, "dhu:nxv", longopts, NULL)) != -1) { 312 while ((c = getopt_long(argc, argv, "dhu:f:nxv", longopts, NULL)) != -1) {
282 switch (c) { 313 switch (c) {
283 case 'd': 314 case 'd':
284 idevice_set_debug_level(1); 315 idevice_set_debug_level(1);
@@ -292,6 +323,15 @@ int main(int argc, char *argv[])
292 free(udid); 323 free(udid);
293 udid = strdup(optarg); 324 udid = strdup(optarg);
294 break; 325 break;
326 case 'f':
327 if (!*optarg) {
328 fprintf(stderr, "ERROR: FORMAT must not be empty!\n");
329 print_usage(argc, argv, 1);
330 return 2;
331 }
332 free(log_format_string);
333 log_format_string = strdup(optarg);
334 break;
295 case 'n': 335 case 'n':
296 use_network = 1; 336 use_network = 1;
297 break; 337 break;
@@ -319,10 +359,23 @@ int main(int argc, char *argv[])
319 return 2; 359 return 2;
320 } 360 }
321 361
362 if (log_format_string != NULL){
363 if (strcmp("packetlogger", log_format_string) == 0){
364 log_format = LOG_FORMAT_PACKETLOGGER;
365 } else if (strcmp("pcap", log_format_string) == 0){
366 log_format = LOG_FORMAT_PCAP;
367 } else {
368 printf("Unknown logging format: '%s'\n", log_format_string);
369 print_usage(argc, argv, 1);
370 return 2;
371 }
372 }
373
322 int num = 0; 374 int num = 0;
323 idevice_info_t *devices = NULL; 375 idevice_info_t *devices = NULL;
324 idevice_get_device_list_extended(&devices, &num); 376 idevice_get_device_list_extended(&devices, &num);
325 idevice_device_list_extended_free(devices); 377 idevice_device_list_extended_free(devices);
378 int oflags;
326 if (num == 0) { 379 if (num == 0) {
327 if (!udid) { 380 if (!udid) {
328 fprintf(stderr, "No device found. Plug in a device or pass UDID with -u to wait for device to be available.\n"); 381 fprintf(stderr, "No device found. Plug in a device or pass UDID with -u to wait for device to be available.\n");
@@ -332,7 +385,27 @@ int main(int argc, char *argv[])
332 } 385 }
333 } 386 }
334 387
335 dump = pcap_dump_open(pcap_open_dead(DLT_BLUETOOTH_HCI_H4_WITH_PHDR, BT_MAX_PACKET_SIZE), out_filename); 388 switch (log_format){
389 case LOG_FORMAT_PCAP:
390 printf("Output Format: PCAP\n");
391 pcap_dumper = pcap_dump_open(pcap_open_dead(DLT_BLUETOOTH_HCI_H4_WITH_PHDR, BT_MAX_PACKET_SIZE), out_filename);
392 break;
393 case LOG_FORMAT_PACKETLOGGER:
394 printf("Output Format: PacketLogger\n");
395 oflags = O_WRONLY | O_CREAT | O_TRUNC;
396#ifdef WIN32
397 default_oflags |= O_BINARY;
398#endif
399 packetlogger_fd = open(out_filename, oflags);
400 if (packetlogger_fd < 0){
401 fprintf(stderr, "Failed to open file %s, errno = %d\n", out_filename, errno);
402 return -2;
403 }
404 break;
405 default:
406 assert(0);
407 return -2;
408 }
336 idevice_event_subscribe(device_event_cb, NULL); 409 idevice_event_subscribe(device_event_cb, NULL);
337 410
338 while (!quit_flag) { 411 while (!quit_flag) {
@@ -342,6 +415,13 @@ int main(int argc, char *argv[])
342 idevice_event_unsubscribe(); 415 idevice_event_unsubscribe();
343 stop_logging(); 416 stop_logging();
344 417
418 if (pcap_dumper) {
419 pcap_dump_close(pcap_dumper);
420 }
421 if (packetlogger_fd >= 0){
422 close(packetlogger_fd);
423 }
424
345 free(udid); 425 free(udid);
346 426
347 return 0; 427 return 0;