2 * androiddump is extcap tool used to capture Android specific stuff
4 * Copyright 2015, Michal Labedzki for Tieto Corporation
6 * Wireshark - Network traffic analyzer
7 * By Gerald Combs <gerald@wireshark.org>
8 * Copyright 1998 Gerald Combs
10 * SPDX-License-Identifier: GPL-2.0+
14 #include "extcap-base.h"
21 #include <wsutil/strtoi.h>
22 #include <wsutil/filesystem.h>
23 #include <wsutil/cmdarg_err.h>
24 #include <wsutil/inet_addr.h>
26 #include "ui/failure_message.h"
28 #ifdef HAVE_NETINET_IN_H
29 # include <netinet/in.h>
36 #ifdef HAVE_SYS_SOCKET_H
37 #include <sys/socket.h>
40 #ifdef HAVE_ARPA_INET_H
41 #include <arpa/inet.h>
44 #ifdef HAVE_SYS_TIME_H
48 /* Configuration options */
49 /* #define ANDROIDDUMP_USE_LIBPCAP */
51 #define PCAP_GLOBAL_HEADER_LENGTH 24
52 #define PCAP_RECORD_HEADER_LENGTH 16
54 #ifdef ANDROIDDUMP_USE_LIBPCAP
55 #include <wsutil/wspcap.h>
57 #include <pcap/bluetooth.h>
59 #ifndef DLT_BLUETOOTH_H4_WITH_PHDR
60 #define DLT_BLUETOOTH_H4_WITH_PHDR 201
63 #ifndef DLT_WIRESHARK_UPPER_PDU
64 #define DLT_WIRESHARK_UPPER_PDU 252
67 #ifndef PCAP_TSTAMP_PRECISION_MICRO
68 #define PCAP_TSTAMP_PRECISION_MICRO 0
71 #ifndef PCAP_TSTAMP_PRECISION_NANO
72 #define PCAP_TSTAMP_PRECISION_NANO 1
75 #include "wiretap/wtap.h"
78 #ifdef ANDROIDDUMP_USE_LIBPCAP
79 #define EXTCAP_ENCAP_BLUETOOTH_H4_WITH_PHDR DLT_BLUETOOTH_H4_WITH_PHDR
80 #define EXTCAP_ENCAP_WIRESHARK_UPPER_PDU DLT_WIRESHARK_UPPER_PDU
81 #define EXTCAP_ENCAP_ETHERNET DLT_EN10MB
82 #define EXTCAP_ENCAP_LINUX_SLL DLT_LINUX_SLL
83 #define EXTCAP_ENCAP_IEEE802_11_RADIO DLT_IEEE802_11_RADIO
84 #define EXTCAP_ENCAP_NETLINK DLT_NETLINK
86 #define EXTCAP_ENCAP_BLUETOOTH_H4_WITH_PHDR WTAP_ENCAP_BLUETOOTH_H4_WITH_PHDR
87 #define EXTCAP_ENCAP_WIRESHARK_UPPER_PDU WTAP_ENCAP_WIRESHARK_UPPER_PDU
88 #define EXTCAP_ENCAP_ETHERNET WTAP_ENCAP_ETHERNET
89 #define EXTCAP_ENCAP_LINUX_SLL WTAP_ENCAP_SLL
90 #define EXTCAP_ENCAP_IEEE802_11_RADIO WTAP_ENCAP_IEEE_802_11_RADIOTAP
91 #define EXTCAP_ENCAP_NETLINK WTAP_ENCAP_NETLINK
94 #define WIRESHARK_UPPER_PDU_TAG_DISSECTOR_NAME 0x000C
96 #define INTERFACE_ANDROID_LOGCAT_MAIN "android-logcat-main"
97 #define INTERFACE_ANDROID_LOGCAT_SYSTEM "android-logcat-system"
98 #define INTERFACE_ANDROID_LOGCAT_RADIO "android-logcat-radio"
99 #define INTERFACE_ANDROID_LOGCAT_EVENTS "android-logcat-events"
100 #define INTERFACE_ANDROID_LOGCAT_TEXT_MAIN "android-logcat-text-main"
101 #define INTERFACE_ANDROID_LOGCAT_TEXT_SYSTEM "android-logcat-text-system"
102 #define INTERFACE_ANDROID_LOGCAT_TEXT_RADIO "android-logcat-text-radio"
103 #define INTERFACE_ANDROID_LOGCAT_TEXT_EVENTS "android-logcat-text-events"
104 #define INTERFACE_ANDROID_LOGCAT_TEXT_CRASH "android-logcat-text-crash"
105 #define INTERFACE_ANDROID_BLUETOOTH_HCIDUMP "android-bluetooth-hcidump"
106 #define INTERFACE_ANDROID_BLUETOOTH_EXTERNAL_PARSER "android-bluetooth-external-parser"
107 #define INTERFACE_ANDROID_BLUETOOTH_BTSNOOP_NET "android-bluetooth-btsnoop-net"
108 #define INTERFACE_ANDROID_TCPDUMP "android-tcpdump"
109 #define INTERFACE_ANDROID_TCPDUMP_FORMAT INTERFACE_ANDROID_TCPDUMP "-%s"
110 #define INTERFACE_ANDROID_TCPDUMP_SERIAL_FORMAT INTERFACE_ANDROID_TCPDUMP_FORMAT "-%s"
112 #define ANDROIDDUMP_VERSION_MAJOR "1"
113 #define ANDROIDDUMP_VERSION_MINOR "1"
114 #define ANDROIDDUMP_VERSION_RELEASE "0"
116 #define SERIAL_NUMBER_LENGTH_MAX 512
117 #define MODEL_NAME_LENGTH_MAX 64
119 #define PACKET_LENGTH 65535
121 #define SOCKET_RW_TIMEOUT_MS 2000
122 #define SOCKET_CONNECT_TIMEOUT_TRIES 10
123 #define SOCKET_CONNECT_DELAY_US 1000 /* (1000us = 1ms) * SOCKET_CONNECT_TIMEOUT_TRIES (10) = 10ms worst-case */
125 #define ADB_HEX4_FORMAT "%04zx"
126 #define ADB_HEX4_LEN 4
129 EXIT_CODE_SUCCESS = 0,
130 EXIT_CODE_CANNOT_GET_INTERFACES_LIST = 1,
131 EXIT_CODE_UNKNOWN_ENCAPSULATION_WIRETAP,
132 EXIT_CODE_UNKNOWN_ENCAPSULATION_LIBPCAP,
133 EXIT_CODE_CANNOT_SAVE_WIRETAP_DUMP,
134 EXIT_CODE_CANNOT_SAVE_LIBPCAP_DUMP,
135 EXIT_CODE_NO_INTERFACE_SPECIFIED,
136 EXIT_CODE_INVALID_INTERFACE,
137 EXIT_CODE_BAD_SIZE_OF_ASSEMBLED_ADB_PACKET_1,
138 EXIT_CODE_BAD_SIZE_OF_ASSEMBLED_ADB_PACKET_2,
139 EXIT_CODE_BAD_SIZE_OF_ASSEMBLED_ADB_PACKET_3,
140 EXIT_CODE_BAD_SIZE_OF_ASSEMBLED_ADB_PACKET_4,
141 EXIT_CODE_BAD_SIZE_OF_ASSEMBLED_ADB_PACKET_5,
142 EXIT_CODE_BAD_SIZE_OF_ASSEMBLED_ADB_PACKET_6,
143 EXIT_CODE_BAD_SIZE_OF_ASSEMBLED_ADB_PACKET_7,
144 EXIT_CODE_BAD_SIZE_OF_ASSEMBLED_ADB_PACKET_8,
145 EXIT_CODE_BAD_SIZE_OF_ASSEMBLED_ADB_PACKET_9,
146 EXIT_CODE_BAD_SIZE_OF_ASSEMBLED_ADB_PACKET_10,
147 EXIT_CODE_BAD_SIZE_OF_ASSEMBLED_ADB_PACKET_11,
148 EXIT_CODE_BAD_SIZE_OF_ASSEMBLED_ADB_PACKET_12,
149 EXIT_CODE_BAD_SIZE_OF_ASSEMBLED_ADB_PACKET_13,
150 EXIT_CODE_BAD_SIZE_OF_ASSEMBLED_ADB_PACKET_14,
151 EXIT_CODE_BAD_SIZE_OF_ASSEMBLED_ADB_PACKET_15,
152 EXIT_CODE_BAD_SIZE_OF_ASSEMBLED_ADB_PACKET_16,
153 EXIT_CODE_BAD_SIZE_OF_ASSEMBLED_ADB_PACKET_17,
154 EXIT_CODE_BAD_SIZE_OF_ASSEMBLED_ADB_PACKET_18,
155 EXIT_CODE_BAD_SIZE_OF_ASSEMBLED_ADB_PACKET_19,
156 EXIT_CODE_BAD_SIZE_OF_ASSEMBLED_ADB_PACKET_20,
157 EXIT_CODE_ERROR_WHILE_SENDING_ADB_PACKET_1,
158 EXIT_CODE_ERROR_WHILE_SENDING_ADB_PACKET_2,
159 EXIT_CODE_ERROR_WHILE_SENDING_ADB_PACKET_3,
160 EXIT_CODE_ERROR_WHILE_SENDING_ADB_PACKET_4,
161 EXIT_CODE_ERROR_WHILE_RECEIVING_ADB_PACKET_STATUS,
162 EXIT_CODE_ERROR_WHILE_RECEIVING_ADB_PACKET_DATA,
163 EXIT_CODE_INVALID_SOCKET_INTERFACES_LIST,
164 EXIT_CODE_INVALID_SOCKET_1,
165 EXIT_CODE_INVALID_SOCKET_2,
166 EXIT_CODE_INVALID_SOCKET_3,
167 EXIT_CODE_INVALID_SOCKET_4,
168 EXIT_CODE_INVALID_SOCKET_5,
169 EXIT_CODE_INVALID_SOCKET_6,
170 EXIT_CODE_INVALID_SOCKET_7,
171 EXIT_CODE_INVALID_SOCKET_8,
172 EXIT_CODE_INVALID_SOCKET_9,
173 EXIT_CODE_INVALID_SOCKET_10,
174 EXIT_CODE_INVALID_SOCKET_11,
175 EXIT_CODE_INVALID_SOCKET_12,
176 EXIT_CODE_GENERIC = -1
180 EXTCAP_BASE_OPTIONS_ENUM,
183 OPT_CONFIG_ADB_SERVER_IP,
184 OPT_CONFIG_ADB_SERVER_TCP_PORT,
185 OPT_CONFIG_LOGCAT_TEXT,
186 OPT_CONFIG_LOGCAT_IGNORE_LOG_BUFFER,
187 OPT_CONFIG_LOGCAT_CUSTOM_OPTIONS,
188 OPT_CONFIG_BT_SERVER_TCP_PORT,
189 OPT_CONFIG_BT_FORWARD_SOCKET,
190 OPT_CONFIG_BT_LOCAL_IP,
191 OPT_CONFIG_BT_LOCAL_TCP_PORT
194 static struct option longopts[] = {
196 { "help", no_argument, NULL, OPT_HELP},
197 { "version", no_argument, NULL, OPT_VERSION},
198 { "adb-server-ip", required_argument, NULL, OPT_CONFIG_ADB_SERVER_IP},
199 { "adb-server-tcp-port", required_argument, NULL, OPT_CONFIG_ADB_SERVER_TCP_PORT},
200 { "logcat-text", optional_argument, NULL, OPT_CONFIG_LOGCAT_TEXT},
201 { "logcat-ignore-log-buffer", optional_argument, NULL, OPT_CONFIG_LOGCAT_IGNORE_LOG_BUFFER},
202 { "logcat-custom-options", required_argument, NULL, OPT_CONFIG_LOGCAT_CUSTOM_OPTIONS},
203 { "bt-server-tcp-port", required_argument, NULL, OPT_CONFIG_BT_SERVER_TCP_PORT},
204 { "bt-forward-socket", required_argument, NULL, OPT_CONFIG_BT_FORWARD_SOCKET},
205 { "bt-local-ip", required_argument, NULL, OPT_CONFIG_BT_LOCAL_IP},
206 { "bt-local-tcp-port", required_argument, NULL, OPT_CONFIG_BT_LOCAL_TCP_PORT},
211 const char *display_name;
212 const char *interface_name;
213 struct interface_t *next;
216 struct exported_pdu_header {
219 /* unsigned char value[0]; */
223 typedef struct _own_pcap_bluetooth_h4_header {
225 } own_pcap_bluetooth_h4_header;
227 typedef struct pcaprec_hdr_s {
228 guint32 ts_sec; /* timestamp seconds */
229 guint32 ts_usec; /* timestamp microseconds */
230 guint32 incl_len; /* number of octets of packet saved in file */
231 guint32 orig_len; /* actual length of packet */
234 /* This fix compilator warning like "warning: cast from 'char *' to 'uint32_t *' (aka 'unsigned int *') increases required alignment from 1 to 4 " */
245 own_pcap_bluetooth_h4_header *value_own_pcap_bluetooth_h4_header;
248 #define SET_DATA(dest, type, src) \
250 data_aligned_t data_aligned; \
252 data_aligned.value_char = src; \
253 dest = data_aligned.type; \
256 struct extcap_dumper {
259 #ifdef ANDROIDDUMP_USE_LIBPCAP
268 static int endless_loop = 1;
271 static inline int is_specified_interface(const char *interface, const char *interface_prefix) {
272 return !strncmp(interface, interface_prefix, strlen(interface_prefix));
275 static gboolean is_logcat_interface(const char *interface) {
276 return is_specified_interface(interface, INTERFACE_ANDROID_LOGCAT_MAIN) ||
277 is_specified_interface(interface, INTERFACE_ANDROID_LOGCAT_SYSTEM) ||
278 is_specified_interface(interface, INTERFACE_ANDROID_LOGCAT_RADIO) ||
279 is_specified_interface(interface, INTERFACE_ANDROID_LOGCAT_EVENTS);
282 static gboolean is_logcat_text_interface(const char *interface) {
283 return is_specified_interface(interface, INTERFACE_ANDROID_LOGCAT_TEXT_MAIN) ||
284 is_specified_interface(interface, INTERFACE_ANDROID_LOGCAT_TEXT_SYSTEM) ||
285 is_specified_interface(interface, INTERFACE_ANDROID_LOGCAT_TEXT_RADIO) ||
286 is_specified_interface(interface, INTERFACE_ANDROID_LOGCAT_TEXT_EVENTS) ||
287 is_specified_interface(interface, INTERFACE_ANDROID_LOGCAT_TEXT_CRASH);
290 static char* get_serial_from_interface(char *interface)
292 static const char* const iface_prefix[] = {
293 INTERFACE_ANDROID_LOGCAT_MAIN,
294 INTERFACE_ANDROID_LOGCAT_SYSTEM,
295 INTERFACE_ANDROID_LOGCAT_RADIO,
296 INTERFACE_ANDROID_LOGCAT_EVENTS,
297 INTERFACE_ANDROID_LOGCAT_TEXT_MAIN,
298 INTERFACE_ANDROID_LOGCAT_TEXT_SYSTEM,
299 INTERFACE_ANDROID_LOGCAT_TEXT_RADIO,
300 INTERFACE_ANDROID_LOGCAT_TEXT_EVENTS,
301 INTERFACE_ANDROID_LOGCAT_TEXT_CRASH,
302 INTERFACE_ANDROID_BLUETOOTH_HCIDUMP,
303 INTERFACE_ANDROID_BLUETOOTH_EXTERNAL_PARSER,
304 INTERFACE_ANDROID_BLUETOOTH_BTSNOOP_NET,
308 const char* curr = NULL;
309 for (i = 0; (curr = iface_prefix[i]); i++) {
310 if (is_specified_interface(interface, curr) &&
311 strlen(interface) > strlen(curr) + 1) {
312 return interface + strlen(curr) + 1;
318 static const char* interface_to_logbuf(char* interface)
320 const char *const adb_log_main = "log:main";
321 const char *const adb_log_system = "log:system";
322 const char *const adb_log_radio = "log:radio";
323 const char *const adb_log_events = "log:events";
324 const char *logbuf = NULL;
326 if (is_specified_interface(interface, INTERFACE_ANDROID_LOGCAT_MAIN))
327 logbuf = adb_log_main;
328 else if (is_specified_interface(interface, INTERFACE_ANDROID_LOGCAT_SYSTEM))
329 logbuf = adb_log_system;
330 else if (is_specified_interface(interface, INTERFACE_ANDROID_LOGCAT_RADIO))
331 logbuf = adb_log_radio;
332 else if (is_specified_interface(interface, INTERFACE_ANDROID_LOGCAT_EVENTS))
333 logbuf = adb_log_events;
338 * General errors and warnings are reported through g_warning() in
341 * Unfortunately, g_warning() may be a macro, so we do it by calling
342 * g_logv() with the appropriate arguments.
345 failure_warning_message(const char *msg_format, va_list ap)
347 g_logv(G_LOG_DOMAIN, G_LOG_LEVEL_WARNING, msg_format, ap);
350 static void useSndTimeout(socket_handle_t sock) {
353 const DWORD socket_timeout = SOCKET_RW_TIMEOUT_MS;
355 res = setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, (const char *) &socket_timeout, (socklen_t)sizeof(socket_timeout));
357 const struct timeval socket_timeout = {
358 .tv_sec = SOCKET_RW_TIMEOUT_MS / 1000,
359 .tv_usec = (SOCKET_RW_TIMEOUT_MS % 1000) * 1000
362 res = setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, &socket_timeout, (socklen_t)sizeof(socket_timeout));
365 g_debug("Can't set socket timeout, using default");
368 static void useNonBlockingConnectTimeout(socket_handle_t sock) {
372 const DWORD socket_timeout = SOCKET_RW_TIMEOUT_MS;
373 unsigned long non_blocking = 1;
375 res_snd = setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, (const char *) &socket_timeout, sizeof(socket_timeout));
376 res_rcv = setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (const char *) &socket_timeout, sizeof(socket_timeout));
378 /* set socket to non-blocking */
379 ioctlsocket(sock, FIONBIO, &non_blocking);
381 const struct timeval socket_timeout = {
382 .tv_sec = SOCKET_RW_TIMEOUT_MS / 1000,
383 .tv_usec = (SOCKET_RW_TIMEOUT_MS % 1000) * 1000
386 res_snd = setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, &socket_timeout, sizeof(socket_timeout));
387 res_rcv = setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &socket_timeout, sizeof(socket_timeout));
390 g_debug("Can't set socket timeout, using default");
392 g_debug("Can't set socket timeout, using default");
395 static void useNormalConnectTimeout(socket_handle_t sock) {
398 const DWORD socket_timeout = 0;
399 unsigned long non_blocking = 0;
401 res_rcv = setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (const char *) &socket_timeout, sizeof(socket_timeout));
402 ioctlsocket(sock, FIONBIO, &non_blocking);
404 const struct timeval socket_timeout = {
405 .tv_sec = SOCKET_RW_TIMEOUT_MS / 1000,
406 .tv_usec = (SOCKET_RW_TIMEOUT_MS % 1000) * 1000
409 res_rcv = setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &socket_timeout, sizeof(socket_timeout));
412 g_debug("Can't set socket timeout, using default");
415 static struct extcap_dumper extcap_dumper_open(char *fifo, int encap) {
416 struct extcap_dumper extcap_dumper;
418 #ifdef ANDROIDDUMP_USE_LIBPCAP
421 pcap = pcap_open_dead_with_tstamp_precision(encap, PACKET_LENGTH, PCAP_TSTAMP_PRECISION_NANO);
422 extcap_dumper.dumper.pcap = pcap_dump_open(pcap, fifo);
423 if (!extcap_dumper.dumper.pcap) {
424 g_warning("Can't open %s for saving packets: %s", pcap_geterr(pcap));
426 exit(EXIT_CODE_CANNOT_SAVE_LIBPCAP_DUMP);
428 extcap_dumper.encap = encap;
429 if (pcap_dump_flush(extcap_dumper.dumper.pcap) == -1) {
430 g_warning("Write to %s failed: %s", g_strerror(errno));
437 extcap_dumper.dumper.wtap = wtap_dump_open(fifo, WTAP_FILE_TYPE_SUBTYPE_PCAP_NSEC, encap, PACKET_LENGTH, FALSE, &err);
438 if (!extcap_dumper.dumper.wtap) {
439 cfile_dump_open_failure_message("androiddump", fifo, err, WTAP_FILE_TYPE_SUBTYPE_PCAP_NSEC);
440 exit(EXIT_CODE_CANNOT_SAVE_WIRETAP_DUMP);
442 extcap_dumper.encap = encap;
443 wtap_dump_flush(extcap_dumper.dumper.wtap);
446 return extcap_dumper;
449 static gboolean extcap_dumper_dump(struct extcap_dumper extcap_dumper,
450 char *fifo, char *buffer,
451 gssize captured_length, gssize reported_length,
452 time_t seconds, int nanoseconds) {
453 #ifdef ANDROIDDUMP_USE_LIBPCAP
454 struct pcap_pkthdr pcap_header;
456 pcap_header.caplen = (bpf_u_int32) captured_length;
457 pcap_header.len = (bpf_u_int32) reported_length;
458 pcap_header.ts.tv_sec = seconds;
459 pcap_header.ts.tv_usec = nanoseconds / 1000;
461 pcap_dump((u_char *) extcap_dumper.dumper.pcap, &pcap_header, buffer);
462 if (pcap_dump_flush(extcap_dumper.dumper.pcap) == -1) {
463 g_warning("Write to %s failed: %s", g_strerror(errno));
468 struct wtap_pkthdr hdr;
470 hdr.presence_flags = WTAP_HAS_TS;
471 hdr.caplen = (guint32) captured_length;
472 hdr.len = (guint32) reported_length;
474 hdr.ts.secs = seconds;
475 hdr.ts.nsecs = (int) nanoseconds;
478 hdr.opt_comment = NULL;
481 hdr.rec_type = REC_TYPE_PACKET;
483 /* NOTE: Try to handle pseudoheaders manually */
484 if (extcap_dumper.encap == EXTCAP_ENCAP_BLUETOOTH_H4_WITH_PHDR) {
487 SET_DATA(direction, value_u32, buffer)
489 hdr.pseudo_header.bthci.sent = GINT32_FROM_BE(*direction) ? 0 : 1;
491 hdr.len -= (guint32)sizeof(own_pcap_bluetooth_h4_header);
492 hdr.caplen -= (guint32)sizeof(own_pcap_bluetooth_h4_header);
494 buffer += sizeof(own_pcap_bluetooth_h4_header);
495 hdr.pkt_encap = WTAP_ENCAP_BLUETOOTH_H4_WITH_PHDR;
497 else if (extcap_dumper.encap == EXTCAP_ENCAP_ETHERNET) {
498 hdr.pkt_encap = WTAP_ENCAP_ETHERNET;
501 hdr.pkt_encap = WTAP_ENCAP_WIRESHARK_UPPER_PDU;
504 if (!wtap_dump(extcap_dumper.dumper.wtap, &hdr, (const guint8 *) buffer, &err, &err_info)) {
505 cfile_write_failure_message("androiddump", NULL, fifo, err, err_info,
506 0, WTAP_FILE_TYPE_SUBTYPE_PCAP_NSEC);
510 wtap_dump_flush(extcap_dumper.dumper.wtap);
517 static socket_handle_t adb_connect(const char *server_ip, unsigned short *server_tcp_port) {
518 socket_handle_t sock;
520 struct sockaddr_in server;
521 struct sockaddr_in client;
525 memset(&server, 0x0, sizeof(server));
527 server.sin_family = AF_INET;
528 server.sin_port = GINT16_TO_BE(*server_tcp_port);
529 ws_inet_pton4(server_ip, &(server.sin_addr.s_addr));
531 if ((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET) {
532 g_warning("Cannot open system TCP socket: %s", strerror(errno));
533 return INVALID_SOCKET;
536 useNonBlockingConnectTimeout(sock);
537 while (tries < SOCKET_CONNECT_TIMEOUT_TRIES) {
538 status = connect(sock, (struct sockaddr *) &server, (socklen_t)sizeof(server));
540 if (status != SOCKET_ERROR)
542 g_usleep(SOCKET_CONNECT_DELAY_US);
544 useNormalConnectTimeout(sock);
546 if (status == SOCKET_ERROR) {
548 /* NOTE: This does not work well - make significant delay while initializing Wireshark.
549 Do fork() then call "adb" also does not make sense, because there is need to
550 do something like sleep(1) to ensure adb is started... system() cannot be used
551 on Windows, because open console window. This helper does not work as expected,
552 so disable it and user must ensure that adb is started (adb start-server,
553 but also all other command start-server automatically)
556 if (_execlp("adb", "adb", "start-server", NULL)) {
558 if (execlp("adb", "adb", "start-server", NULL)) {
560 errmsg("WARNING: Cannot execute system command to start adb: %s", strerror(errno));
562 return INVALID_SOCKET;
565 if (connect(sock, (struct sockaddr *) &server, (socklen_t)sizeof(server)) == SOCKET_ERROR) {
566 g_warning("Cannot connect to ADB: <%s> Please check that adb daemon is running.", strerror(errno));
568 return INVALID_SOCKET;
571 g_debug("Cannot connect to ADB: <%s> Please check that adb daemon is running.", strerror(errno));
573 return INVALID_SOCKET;
577 length = sizeof(client);
578 if (getsockname(sock, (struct sockaddr *) &client, &length)) {
579 g_warning("getsockname: %s", strerror(errno));
581 return INVALID_SOCKET;
584 if (length != sizeof(client)) {
585 g_warning("incorrect length");
587 return INVALID_SOCKET;
590 g_debug("Client port %u", GUINT16_FROM_BE(client.sin_port));
596 static char *adb_send_and_receive(socket_handle_t sock, const char *adb_service,
597 char *buffer, size_t buffer_length, size_t *data_length) {
598 size_t used_buffer_length;
599 size_t bytes_to_read;
604 size_t adb_service_length;
606 adb_service_length = strlen(adb_service);
607 if (adb_service_length > INT_MAX) {
608 g_warning("Service name too long when sending <%s> to ADB daemon", adb_service);
614 /* 8 bytes of hex length + terminating NUL */
615 if (buffer_length < 9) {
616 g_warning("Buffer for response too short while sending <%s> to ADB daemon", adb_service);
622 g_snprintf(buffer, (gulong)buffer_length, ADB_HEX4_FORMAT, adb_service_length);
623 result = send(sock, buffer, ADB_HEX4_LEN, 0);
624 if (result < ADB_HEX4_LEN) {
625 g_warning("Error while sending <%s> length to ADB daemon", adb_service);
629 result = send(sock, adb_service, (int) adb_service_length, 0);
630 if (result != (gssize) adb_service_length) {
631 g_warning("Error while sending <%s> to ADB daemon", adb_service);
637 used_buffer_length = 0;
638 while (used_buffer_length < 8) {
639 bytes_to_read = buffer_length - used_buffer_length;
640 if (bytes_to_read > INT_MAX)
641 bytes_to_read = INT_MAX;
642 result = recv(sock, buffer + used_buffer_length, (int)bytes_to_read, 0);
645 g_warning("Broken socket connection while fetching reply status for <%s>", adb_service);
651 used_buffer_length += result;
654 memcpy(status, buffer, 4);
655 tmp_buffer = buffer[8];
657 if (!ws_hexstrtou32(buffer + 4, NULL, &length)) {
658 g_warning("Invalid reply length <%s> while reading reply for <%s>", buffer + 4, adb_service);
663 buffer[8] = tmp_buffer;
665 if (buffer_length < length + 8) {
666 g_warning("Buffer for response too short while sending <%s> to ADB daemon", adb_service);
672 while (used_buffer_length < length + 8) {
673 bytes_to_read = buffer_length - used_buffer_length;
674 if (bytes_to_read > INT_MAX)
675 bytes_to_read = INT_MAX;
676 result = recv(sock, buffer + used_buffer_length, (int)bytes_to_read, 0);
679 g_warning("Broken socket connection while reading reply for <%s>", adb_service);
685 used_buffer_length += result;
689 *data_length = used_buffer_length - 8;
691 if (memcmp(status, "OKAY", 4)) {
692 g_warning("Error while receiving by ADB for <%s>", adb_service);
702 static char *adb_send_and_read(socket_handle_t sock, const char *adb_service, char *buffer,
703 int buffer_length, gssize *data_length) {
704 gssize used_buffer_length;
707 size_t adb_service_length;
709 adb_service_length = strlen(adb_service);
710 g_snprintf(buffer, buffer_length, ADB_HEX4_FORMAT, adb_service_length);
712 result = send(sock, buffer, ADB_HEX4_LEN, 0);
713 if (result < ADB_HEX4_LEN) {
714 g_warning("Error while sending <%s> to ADB daemon", adb_service);
718 result = send(sock, adb_service, (int) adb_service_length, 0);
719 if (result != (gssize) adb_service_length) {
720 g_warning("Error while sending <%s> to ADB", adb_service);
726 used_buffer_length = 0;
727 while (used_buffer_length < 4) {
728 result = recv(sock, buffer + used_buffer_length, (int)(buffer_length - used_buffer_length), 0);
731 g_warning("Broken socket connection while fetching reply status for <%s>", adb_service);
736 used_buffer_length += result;
739 memcpy(status, buffer, 4);
742 result= recv(sock, buffer + used_buffer_length, (int)(buffer_length - used_buffer_length), 0);
745 g_warning("Broken socket connection while reading reply for <%s>", adb_service);
748 } else if (result == 0) {
752 used_buffer_length += result;
756 *data_length = used_buffer_length - 4;
758 if (memcmp(status, "OKAY", 4)) {
759 g_warning("Error while receiving by ADB for <%s>", adb_service);
769 static int adb_send(socket_handle_t sock, const char *adb_service) {
771 int used_buffer_length;
773 size_t adb_service_length;
775 adb_service_length = strlen(adb_service);
776 g_snprintf(buffer, sizeof(buffer), ADB_HEX4_FORMAT, adb_service_length);
778 result = send(sock, buffer, ADB_HEX4_LEN, 0);
779 if (result < ADB_HEX4_LEN) {
780 g_warning("Error while sending <%s> to ADB daemon", adb_service);
781 return EXIT_CODE_ERROR_WHILE_SENDING_ADB_PACKET_1;
784 result = send(sock, adb_service, (int) adb_service_length, 0);
785 if (result != (gssize) adb_service_length) {
786 g_warning("Error while sending <%s> to ADB", adb_service);
787 return EXIT_CODE_ERROR_WHILE_SENDING_ADB_PACKET_1;
790 used_buffer_length = 0;
791 while (used_buffer_length < 4) {
792 result = recv(sock, buffer + used_buffer_length, 4 - used_buffer_length, 0);
795 g_warning("Broken socket connection while fetching reply status for <%s>", adb_service);
797 return EXIT_CODE_ERROR_WHILE_RECEIVING_ADB_PACKET_STATUS;
800 used_buffer_length += (int)result;
803 if (memcmp(buffer, "OKAY", 4)) {
804 g_debug("Error while receiving by ADB for <%s>", adb_service);
806 return EXIT_CODE_ERROR_WHILE_RECEIVING_ADB_PACKET_DATA;
809 return EXIT_CODE_SUCCESS;
813 static socket_handle_t
814 adb_connect_transport(const char *server_ip, unsigned short *server_tcp_port,
815 const char* serial_number)
817 static const char *const adb_transport_serial_templace = "host:transport:%s";
818 static const char *const adb_transport_any = "host:transport-any";
819 char transport_buf[80];
820 const char* transport = transport_buf;
821 socket_handle_t sock;
824 sock = adb_connect(server_ip, server_tcp_port);
825 if (sock == INVALID_SOCKET) {
826 g_warning("Error while connecting to adb server");
830 if (!serial_number) {
831 transport = adb_transport_any;
833 result = g_snprintf(transport_buf, sizeof(transport_buf), adb_transport_serial_templace, serial_number);
834 if (result <= 0 || result > (int)sizeof(transport_buf)) {
835 g_warning("Error while completing adb packet for transport");
837 return INVALID_SOCKET;
841 result = adb_send(sock, transport);
843 g_warning("Error while setting adb transport for <%s>", transport_buf);
845 return INVALID_SOCKET;
851 static void new_interface(extcap_parameters * extcap_conf, const gchar *interface_id,
852 const gchar *model_name, const gchar *serial_number, const gchar *display_name)
854 char *interface = g_strdup_printf("%s-%s", interface_id, serial_number);
855 char *ifdisplay = g_strdup_printf("%s %s %s", display_name, model_name, serial_number);
857 if (is_specified_interface(interface, INTERFACE_ANDROID_BLUETOOTH_HCIDUMP) ||
858 is_specified_interface(interface, INTERFACE_ANDROID_BLUETOOTH_EXTERNAL_PARSER) ||
859 is_specified_interface(interface, INTERFACE_ANDROID_BLUETOOTH_BTSNOOP_NET)) {
861 extcap_base_register_interface_ext(extcap_conf, interface, ifdisplay, 99, "BluetoothH4", "Bluetooth HCI UART transport layer plus pseudo-header" );
862 } else if (is_logcat_interface(interface) || is_logcat_text_interface(interface)) {
863 extcap_base_register_interface(extcap_conf, interface, ifdisplay, 252, "Upper PDU" );
864 } else if (is_specified_interface(interface, INTERFACE_ANDROID_TCPDUMP)) {
865 extcap_base_register_interface(extcap_conf, interface, ifdisplay, 1, "Ethernet");
872 static void new_fake_interface_for_list_dlts(extcap_parameters * extcap_conf,
875 if (is_specified_interface(ifname, INTERFACE_ANDROID_BLUETOOTH_HCIDUMP) ||
876 is_specified_interface(ifname, INTERFACE_ANDROID_BLUETOOTH_EXTERNAL_PARSER) ||
877 is_specified_interface(ifname, INTERFACE_ANDROID_BLUETOOTH_BTSNOOP_NET)) {
878 extcap_base_register_interface_ext(extcap_conf, ifname, ifname, 99, "BluetoothH4", "Bluetooth HCI UART transport layer plus pseudo-header" );
879 } else if (is_logcat_interface(ifname) || is_logcat_text_interface(ifname)) {
880 extcap_base_register_interface(extcap_conf, ifname, ifname, 252, "Upper PDU" );
881 } else if (is_specified_interface(ifname, INTERFACE_ANDROID_TCPDUMP)) {
882 extcap_base_register_interface(extcap_conf, ifname, ifname, 1, "Ethernet");
887 static int add_tcpdump_interfaces(extcap_parameters * extcap_conf, const char *adb_server_ip, unsigned short *adb_server_tcp_port, const char *serial_number)
889 static const char *const adb_tcpdump_list = "shell:tcpdump -D";
890 static const char *const regex_ifaces = "\\d+\\.(?<iface>\\S+)(\\s+?(?:(?:\\(.*\\))*)(\\s*?\\[(?<flags>.*?)\\])?)?";
891 static char recv_buffer[PACKET_LENGTH];
894 socket_handle_t sock;
895 GRegex* regex = NULL;
897 GMatchInfo *match = NULL;
900 gboolean flags_supported;
902 sock = adb_connect_transport(adb_server_ip, adb_server_tcp_port, serial_number);
903 if (sock == INVALID_SOCKET) {
904 g_warning("Failed to connect to adb server");
905 return EXIT_CODE_GENERIC;
908 response = adb_send_and_read(sock, adb_tcpdump_list, recv_buffer, sizeof(recv_buffer), &data_length);
912 g_warning("Failed to get list of available tcpdump interfaces");
913 return EXIT_CODE_GENERIC;
915 response[data_length] = '\0';
917 regex = g_regex_new(regex_ifaces, (GRegexCompileFlags)0, (GRegexMatchFlags)0, &err);
919 g_warning("Failed to compile regex for tcpdump interface matching");
920 return EXIT_CODE_GENERIC;
923 flags_supported = (strstr(response, "[") != 0) && (strstr(response, "]") != 0);
925 tok = strtok(response, "\n");
926 while (tok != NULL) {
927 g_regex_match(regex, tok, (GRegexMatchFlags)0, &match);
928 if (g_match_info_matches(match)) {
929 gchar *iface = g_match_info_fetch_named(match, "iface");
930 gchar *flags = g_match_info_fetch_named(match, "flags");
932 if (!flags_supported || (flags && strstr(flags, "Up"))) {
933 g_snprintf(iface_name, sizeof(iface_name), INTERFACE_ANDROID_TCPDUMP_FORMAT, iface);
934 new_interface(extcap_conf, iface_name, iface, serial_number, "Android tcpdump");
939 g_match_info_free(match);
940 tok = strtok(NULL, "\n");
942 g_regex_unref(regex);
947 static int register_interfaces(extcap_parameters * extcap_conf, const char *adb_server_ip, unsigned short *adb_server_tcp_port) {
948 static char packet[PACKET_LENGTH];
949 static char helpful_packet[PACKET_LENGTH];
950 char check_port_buf[80];
954 size_t device_length;
955 socket_handle_t sock;
956 const char *adb_check_port_templace = "shell:cat /proc/%s/net/tcp";
957 const char *adb_devices = "host:devices-l";
958 const char *adb_api_level = "shell:getprop ro.build.version.sdk";
959 const char *adb_hcidump_version = "shell:hcidump --version";
960 const char *adb_ps_droid_bluetooth = "shell:ps droid.bluetooth";
961 const char *adb_ps_bluetooth_app = "shell:ps com.android.bluetooth";
962 const char *adb_ps_with_grep = "shell:ps | grep com.android.bluetooth";
963 char serial_number[SERIAL_NUMBER_LENGTH_MAX];
964 char model_name[MODEL_NAME_LENGTH_MAX];
972 int disable_interface;
974 /* NOTE: It seems that "adb devices" and "adb shell" closed connection
975 so cannot send next command after them, there is need to reconnect */
977 sock = adb_connect(adb_server_ip, adb_server_tcp_port);
978 if (sock == INVALID_SOCKET)
979 return EXIT_CODE_INVALID_SOCKET_INTERFACES_LIST;
981 device_list = adb_send_and_receive(sock, adb_devices, packet, sizeof(packet), &device_length);
985 g_warning("Cannot get list of interfaces from devices");
987 return EXIT_CODE_CANNOT_GET_INTERFACES_LIST;
990 device_list[device_length] = '\0';
991 pos = (char *) device_list;
993 while (pos < (char *) (device_list + device_length)) {
995 pos = strchr(pos, ' ');
997 result = (int) (pos - prev_pos);
998 pos = strchr(pos, '\n') + 1;
999 if (result >= (int) sizeof(serial_number)) {
1000 g_warning("Serial number too long, ignore device");
1003 memcpy(serial_number, prev_pos, result);
1004 serial_number[result] = '\0';
1006 model_name[0] = '\0';
1007 model_pos = g_strstr_len(i_pos, pos - i_pos, "model:");
1009 device_pos = g_strstr_len(i_pos, pos - i_pos, "device:");
1010 if (device_pos && device_pos - model_pos - 6 - 1 < MODEL_NAME_LENGTH_MAX) {
1011 memcpy(model_name, model_pos + 6, device_pos - model_pos - 6 - 1);
1012 model_name[device_pos - model_pos - 6 - 1] = '\0';
1016 if (model_name[0] == '\0')
1017 strcpy(model_name, "unknown");
1019 g_debug("Processing device: \"%s\" <%s>" , serial_number, model_name);
1021 /* Function will only add tcpdump interfaces if tcpdump is present on the device */
1022 result = add_tcpdump_interfaces(extcap_conf, adb_server_ip, adb_server_tcp_port, serial_number );
1024 g_warning("Error while adding tcpdump interfaces");
1027 sock = adb_connect_transport(adb_server_ip, adb_server_tcp_port, serial_number);
1028 if (sock == INVALID_SOCKET) continue;
1030 response = adb_send_and_read(sock, adb_api_level, helpful_packet, sizeof(helpful_packet), &data_length);
1034 g_warning("Error on socket: <%s>", helpful_packet);
1038 response[data_length] = '\0';
1039 api_level = (int) g_ascii_strtoll(response, NULL, 10);
1040 g_debug("Android API Level for %s is %i", serial_number, api_level);
1042 if (api_level < 21) {
1043 new_interface(extcap_conf, INTERFACE_ANDROID_LOGCAT_MAIN, model_name, serial_number, "Android Logcat Main");
1044 new_interface(extcap_conf, INTERFACE_ANDROID_LOGCAT_SYSTEM, model_name, serial_number, "Android Logcat System");
1045 new_interface(extcap_conf, INTERFACE_ANDROID_LOGCAT_RADIO, model_name, serial_number, "Android Logcat Radio");
1046 new_interface(extcap_conf, INTERFACE_ANDROID_LOGCAT_EVENTS, model_name, serial_number, "Android Logcat Events");
1048 new_interface(extcap_conf, INTERFACE_ANDROID_LOGCAT_TEXT_MAIN, model_name, serial_number, "Android Logcat Main");
1049 new_interface(extcap_conf, INTERFACE_ANDROID_LOGCAT_TEXT_SYSTEM, model_name, serial_number, "Android Logcat System");
1050 new_interface(extcap_conf, INTERFACE_ANDROID_LOGCAT_TEXT_RADIO, model_name, serial_number, "Android Logcat Radio");
1051 new_interface(extcap_conf, INTERFACE_ANDROID_LOGCAT_TEXT_EVENTS, model_name, serial_number, "Android Logcat Events");
1053 new_interface(extcap_conf, INTERFACE_ANDROID_LOGCAT_TEXT_MAIN, model_name, serial_number, "Android Logcat Main");
1054 new_interface(extcap_conf, INTERFACE_ANDROID_LOGCAT_TEXT_SYSTEM, model_name, serial_number, "Android Logcat System");
1055 new_interface(extcap_conf, INTERFACE_ANDROID_LOGCAT_TEXT_RADIO, model_name, serial_number, "Android Logcat Radio");
1056 new_interface(extcap_conf, INTERFACE_ANDROID_LOGCAT_TEXT_EVENTS, model_name, serial_number, "Android Logcat Events");
1057 new_interface(extcap_conf, INTERFACE_ANDROID_LOGCAT_TEXT_CRASH, model_name, serial_number, "Android Logcat Crash");
1060 if (api_level >= 5 && api_level < 17) {
1061 disable_interface = 0;
1063 sock = adb_connect_transport(adb_server_ip, adb_server_tcp_port, serial_number);
1064 if (sock == INVALID_SOCKET) continue;
1066 response = adb_send_and_read(sock, adb_hcidump_version, helpful_packet, sizeof(helpful_packet), &data_length);
1069 if (!response || data_length < 1) {
1070 g_warning("Error while getting hcidump version by <%s> (%p len=%"G_GSSIZE_FORMAT")",
1071 adb_hcidump_version, (void*)response, data_length);
1072 g_debug("Android hcidump version for %s is unknown", serial_number);
1073 disable_interface = 1;
1075 response[data_length] = '\0';
1077 if (g_ascii_strtoull(response, NULL, 10) == 0) {
1078 g_debug("Android hcidump version for %s is unknown", serial_number);
1079 disable_interface = 1;
1081 g_debug("Android hcidump version for %s is %s", serial_number, response);
1085 if (!disable_interface) {
1086 new_interface(extcap_conf, INTERFACE_ANDROID_BLUETOOTH_HCIDUMP, model_name, serial_number, "Android Bluetooth Hcidump");
1090 if (api_level >= 17 && api_level < 21) {
1091 disable_interface = 0;
1092 sock = adb_connect_transport(adb_server_ip, adb_server_tcp_port, serial_number);
1093 if (sock == INVALID_SOCKET) continue;
1095 response = adb_send_and_read(sock, adb_ps_droid_bluetooth, helpful_packet, sizeof(helpful_packet), &data_length);
1097 if (!response || data_length < 1) {
1098 g_warning("Error while getting Bluetooth application process id by <%s> "
1099 "(%p len=%"G_GSSIZE_FORMAT")", adb_hcidump_version, (void*)response, data_length);
1100 g_debug( "Android Bluetooth application PID for %s is unknown", serial_number);
1101 disable_interface = 1;
1106 memset(pid, 0, sizeof(pid));
1107 response[data_length] = '\0';
1109 data_str = strchr(response, '\n');
1110 if (data_str && sscanf(data_str, "%*s %15s", pid) == 1) {
1111 g_debug("Android Bluetooth application PID for %s is %s", serial_number, pid);
1113 result = g_snprintf(check_port_buf, sizeof(check_port_buf), adb_check_port_templace, pid);
1114 if (result <= 0 || result > (int)sizeof(check_port_buf)) {
1115 g_warning("Error while completing adb packet");
1116 return EXIT_CODE_BAD_SIZE_OF_ASSEMBLED_ADB_PACKET_6;
1119 sock = adb_connect_transport(adb_server_ip, adb_server_tcp_port, serial_number);
1120 if (sock == INVALID_SOCKET) continue;
1122 response = adb_send_and_read(sock, check_port_buf, helpful_packet, sizeof(helpful_packet), &data_length);
1126 disable_interface = 1;
1128 response[data_length] = '\0';
1130 data_str = strchr(response, '\n');
1131 if (data_str && sscanf(data_str, "%*s %15s", pid) == 1 && strlen(pid) > 10 && strcmp(pid + 9, "10EA") == 0) {
1132 g_debug("Bluedroid External Parser Port for %s is %s", serial_number, pid + 9);
1134 disable_interface = 1;
1135 g_debug("Bluedroid External Parser Port for %s is unknown", serial_number);
1139 disable_interface = 1;
1140 g_debug("Android Bluetooth application PID for %s is unknown", serial_number);
1144 if (!disable_interface) {
1145 new_interface(extcap_conf, INTERFACE_ANDROID_BLUETOOTH_EXTERNAL_PARSER, model_name, serial_number, "Android Bluetooth External Parser");
1149 if (api_level >= 21) {
1151 disable_interface = 0;
1153 if (api_level >= 24) {
1154 ps_cmd = adb_ps_with_grep;
1155 } else if (api_level >= 23) {
1156 ps_cmd = adb_ps_bluetooth_app;
1158 ps_cmd = adb_ps_droid_bluetooth;
1160 sock = adb_connect_transport(adb_server_ip, adb_server_tcp_port, serial_number);
1161 if (sock == INVALID_SOCKET) continue;
1163 response = adb_send_and_read(sock, ps_cmd, helpful_packet, sizeof(helpful_packet), &data_length);
1166 if (!response || data_length < 1) {
1167 g_warning("Error while getting Bluetooth application process id by <%s> "
1168 "(%p len=%"G_GSSIZE_FORMAT")", adb_hcidump_version, (void*)response, data_length);
1169 g_debug("Android Bluetooth application PID for %s is unknown", serial_number);
1170 disable_interface = 1;
1175 memset(pid, 0, sizeof(pid));
1176 response[data_length] = '\0';
1178 if (api_level >= 24)
1179 data_str = response;
1181 data_str = strchr(response, '\n');
1183 if (data_str && sscanf(data_str, "%*s %15s", pid) == 1) {
1184 g_debug("Android Bluetooth application PID for %s is %s", serial_number, pid);
1186 result = g_snprintf(check_port_buf, sizeof(check_port_buf), adb_check_port_templace, pid);
1187 if (result <= 0 || result > (int)sizeof(check_port_buf)) {
1188 g_warning("Error while completing adb packet");
1189 return EXIT_CODE_BAD_SIZE_OF_ASSEMBLED_ADB_PACKET_9;
1192 sock = adb_connect_transport(adb_server_ip, adb_server_tcp_port, serial_number);
1193 if (sock == INVALID_SOCKET) continue;
1195 response = adb_send_and_read(sock, check_port_buf, helpful_packet, sizeof(helpful_packet), &data_length);
1199 disable_interface = 1;
1201 response[data_length] = '\0';
1203 data_str = strchr(response, '\n');
1204 if (data_str && sscanf(data_str, "%*s %15s", pid) == 1 && strlen(pid) > 10 && strcmp(pid + 9, "22A8") == 0) {
1205 g_debug("Btsnoop Net Port for %s is %s", serial_number, pid + 9);
1207 disable_interface = 1;
1208 g_debug("Btsnoop Net Port for %s is unknown", serial_number);
1212 disable_interface = 1;
1213 g_debug("Android Bluetooth application PID for %s is unknown", serial_number);
1217 if (!disable_interface) {
1218 new_interface(extcap_conf, INTERFACE_ANDROID_BLUETOOTH_BTSNOOP_NET, model_name, serial_number, "Android Bluetooth Btsnoop Net");
1223 return EXIT_CODE_SUCCESS;
1226 static int list_config(char *interface) {
1227 int ret = EXIT_CODE_INVALID_INTERFACE;
1231 g_warning("No interface specified.");
1232 return EXIT_CODE_NO_INTERFACE_SPECIFIED;
1235 if (is_specified_interface(interface, INTERFACE_ANDROID_BLUETOOTH_EXTERNAL_PARSER)) {
1236 printf("arg {number=%u}{call=--adb-server-ip}{display=ADB Server IP Address}{type=string}{default=127.0.0.1}\n", inc++);
1237 printf("arg {number=%u}{call=--adb-server-tcp-port}{display=ADB Server TCP Port}{type=integer}{range=0,65535}{default=5037}\n", inc++);
1238 printf("arg {number=%u}{call=--bt-server-tcp-port}{display=Bluetooth Server TCP Port}{type=integer}{range=0,65535}{default=4330}\n", inc++);
1239 printf("arg {number=%u}{call=--bt-forward-socket}{display=Forward Bluetooth Socket}{type=boolean}{default=false}\n", inc++);
1240 printf("arg {number=%u}{call=--bt-local-ip}{display=Bluetooth Local IP Address}{type=string}{default=127.0.0.1}\n", inc++);
1241 printf("arg {number=%u}{call=--bt-local-tcp-port}{display=Bluetooth Local TCP Port}{type=integer}{range=0,65535}{default=4330}{tooltip=Used to do \"adb forward tcp:LOCAL_TCP_PORT tcp:SERVER_TCP_PORT\"}\n", inc++);
1242 printf("arg {number=%u}{call=--verbose}{display=Verbose/Debug output on console}{type=boolean}{default=false}\n", inc++);
1243 ret = EXIT_CODE_SUCCESS;
1244 } else if (is_specified_interface(interface, INTERFACE_ANDROID_BLUETOOTH_HCIDUMP) ||
1245 is_specified_interface(interface, INTERFACE_ANDROID_BLUETOOTH_BTSNOOP_NET) ||
1246 is_specified_interface(interface, INTERFACE_ANDROID_TCPDUMP)) {
1247 printf("arg {number=%u}{call=--adb-server-ip}{display=ADB Server IP Address}{type=string}{default=127.0.0.1}\n", inc++);
1248 printf("arg {number=%u}{call=--adb-server-tcp-port}{display=ADB Server TCP Port}{type=integer}{range=0,65535}{default=5037}\n", inc++);
1249 printf("arg {number=%u}{call=--verbose}{display=Verbose/Debug output on console}{type=boolean}{default=false}\n", inc++);
1250 ret = EXIT_CODE_SUCCESS;
1251 } else if (is_logcat_interface(interface)) {
1252 printf("arg {number=%u}{call=--adb-server-ip}{display=ADB Server IP Address}{type=string}{default=127.0.0.1}\n", inc++);
1253 printf("arg {number=%u}{call=--adb-server-tcp-port}{display=ADB Server TCP Port}{type=integer}{range=0,65535}{default=5037}\n", inc++);
1254 printf("arg {number=%u}{call=--logcat-text}{display=Use text logcat}{type=boolean}{default=false}\n", inc++);
1255 printf("arg {number=%u}{call=--logcat-ignore-log-buffer}{display=Ignore log buffer}{type=boolean}{default=false}\n", inc++);
1256 printf("arg {number=%u}{call=--logcat-custom-options}{display=Custom logcat parameters}{type=string}\n", inc++);
1257 printf("arg {number=%u}{call=--verbose}{display=Verbose/Debug output on console}{type=boolean}{default=false}\n", inc++);
1258 ret = EXIT_CODE_SUCCESS;
1259 } else if (is_logcat_text_interface(interface)) {
1260 printf("arg {number=%u}{call=--adb-server-ip}{display=ADB Server IP Address}{type=string}{default=127.0.0.1}\n", inc++);
1261 printf("arg {number=%u}{call=--adb-server-tcp-port}{display=ADB Server TCP Port}{type=integer}{range=0,65535}{default=5037}\n", inc++);
1262 printf("arg {number=%u}{call=--logcat-ignore-log-buffer}{display=Ignore log buffer}{type=boolean}{default=false}\n", inc++);
1263 printf("arg {number=%u}{call=--logcat-custom-options}{display=Custom logcat parameters}{type=string}\n", inc++);
1264 printf("arg {number=%u}{call=--verbose}{display=Verbose/Debug output on console}{type=boolean}{default=false}\n", inc++);
1265 ret = EXIT_CODE_SUCCESS;
1268 if (ret != EXIT_CODE_SUCCESS)
1269 g_warning("Invalid interface: <%s>", interface);
1271 extcap_config_debug(&inc);
1276 /*----------------------------------------------------------------------------*/
1277 /* Android Bluetooth Hcidump */
1278 /*----------------------------------------------------------------------------*/
1280 static int capture_android_bluetooth_hcidump(char *interface, char *fifo,
1281 const char *adb_server_ip, unsigned short *adb_server_tcp_port) {
1282 struct extcap_dumper extcap_dumper;
1283 static char data[PACKET_LENGTH];
1284 static char packet[PACKET_LENGTH];
1286 gssize used_buffer_length = 0;
1287 socket_handle_t sock = INVALID_SOCKET;
1288 const char *adb_shell_hcidump = "shell:hcidump -R -t";
1289 const char *adb_shell_su_hcidump = "shell:su -c hcidump -R -t";
1291 char *serial_number;
1293 unsigned int captured_length;
1297 own_pcap_bluetooth_h4_header *h4_header;
1298 gint64 raw_length = 0;
1299 gint64 frame_length;
1302 char direction_character;
1304 SET_DATA(h4_header, value_own_pcap_bluetooth_h4_header, packet);
1306 extcap_dumper = extcap_dumper_open(fifo, EXTCAP_ENCAP_BLUETOOTH_H4_WITH_PHDR);
1308 serial_number = get_serial_from_interface(interface);
1309 sock = adb_connect_transport(adb_server_ip, adb_server_tcp_port, serial_number);
1310 if (sock == INVALID_SOCKET)
1311 return EXIT_CODE_INVALID_SOCKET_3;
1313 result = adb_send(sock, adb_shell_hcidump);
1315 g_warning("Error while starting capture by sending command: %s", adb_shell_hcidump);
1317 return EXIT_CODE_GENERIC;
1320 while (endless_loop) {
1324 length = recv(sock, data + used_buffer_length, (int)(PACKET_LENGTH - used_buffer_length), 0);
1326 #if EWOULDBLOCK != EAGAIN
1327 || errno == EWOULDBLOCK
1332 else if (errno != 0) {
1333 g_warning("ERROR capture: %s", strerror(errno));
1335 return EXIT_CODE_GENERIC;
1339 g_warning("Broken socket connection.");
1341 return EXIT_CODE_GENERIC;
1344 used_buffer_length += length;
1345 i_position = (char *) memchr(data, '\n', used_buffer_length);
1346 if (i_position && i_position < data + used_buffer_length) {
1347 char *state_line_position = i_position + 1;
1349 if (!strncmp(data, "/system/bin/sh: hcidump: not found", 34)) {
1350 g_warning("Command not found for <%s>", adb_shell_hcidump);
1352 return EXIT_CODE_GENERIC;
1355 i_position = (char *) memchr(i_position + 1, '\n', used_buffer_length);
1358 if (!strncmp(state_line_position, "Can't access device: Permission denied", 38)) {
1359 g_warning("No permission for command <%s>", adb_shell_hcidump);
1360 used_buffer_length = 0;
1362 sock = INVALID_SOCKET;
1365 memmove(data, i_position, used_buffer_length - (i_position - data));
1366 used_buffer_length = used_buffer_length - (gssize)(i_position - data);
1372 if (sock == INVALID_SOCKET) {
1373 sock = adb_connect_transport(adb_server_ip, adb_server_tcp_port, serial_number);
1374 if (sock == INVALID_SOCKET)
1375 return EXIT_CODE_INVALID_SOCKET_4;
1377 result = adb_send(sock, adb_shell_su_hcidump);
1379 g_warning("Error while starting capture by sending command: <%s>", adb_shell_su_hcidump);
1381 return EXIT_CODE_GENERIC;
1384 used_buffer_length = 0;
1385 while (endless_loop) {
1389 length = recv(sock, data + used_buffer_length, (int)(PACKET_LENGTH - used_buffer_length), 0);
1391 #if EWOULDBLOCK != EAGAIN
1392 || errno == EWOULDBLOCK
1397 else if (errno != 0) {
1398 g_warning("ERROR capture: %s", strerror(errno));
1400 return EXIT_CODE_GENERIC;
1404 g_warning("Broken socket connection.");
1406 return EXIT_CODE_GENERIC;
1409 used_buffer_length += length;
1410 i_position = (char *) memchr(data, '\n', used_buffer_length);
1411 if (i_position && i_position < data + used_buffer_length) {
1412 if (!strncmp(data, "/system/bin/sh: su: not found", 29)) {
1413 g_warning("Command 'su' not found for <%s>", adb_shell_su_hcidump);
1415 return EXIT_CODE_GENERIC;
1418 i_position = (char *) memchr(i_position + 1, '\n', used_buffer_length);
1421 memmove(data, i_position, used_buffer_length - (i_position - data));
1422 used_buffer_length = used_buffer_length - (gssize)(i_position - data);
1429 while (endless_loop) {
1431 length = recv(sock, data + used_buffer_length, (int)(PACKET_LENGTH - used_buffer_length), 0);
1433 #if EWOULDBLOCK != EAGAIN
1434 || errno == EWOULDBLOCK
1439 else if (errno != 0) {
1440 g_warning("ERROR capture: %s", strerror(errno));
1442 return EXIT_CODE_GENERIC;
1446 g_warning("Broken socket connection.");
1448 return EXIT_CODE_GENERIC;
1451 while (endless_loop) {
1452 if (used_buffer_length + length >= 1) {
1453 hex_data = data + 29;
1454 hex = g_ascii_strtoll(hex_data, &new_hex_data, 16);
1456 if ((hex == 0x01 && used_buffer_length + length >= 4) ||
1457 (hex == 0x02 && used_buffer_length + length >= 5) ||
1458 (hex == 0x04 && used_buffer_length + length >= 3)) {
1461 hex_data = new_hex_data;
1462 hex = g_ascii_strtoll(hex_data, &new_hex_data, 16);
1463 if (hex < 0 || hex >= 256 || hex_data == new_hex_data) {
1464 g_warning("data format %s", strerror(errno));
1466 return EXIT_CODE_GENERIC;
1469 hex_data = new_hex_data;
1470 hex = g_ascii_strtoll(hex_data, &new_hex_data, 16);
1471 if (hex < 0 || hex >= 256 || hex_data == new_hex_data) {
1472 g_warning("data format %s", strerror(errno));
1474 return EXIT_CODE_GENERIC;
1477 hex_data = new_hex_data;
1478 hex = g_ascii_strtoll(hex_data, &new_hex_data, 16);
1480 raw_length = hex + 4;
1481 } else if (hex == 0x04) {
1482 hex_data = new_hex_data;
1483 hex = g_ascii_strtoll(hex_data, &new_hex_data, 16);
1484 if (hex < 0 || hex >= 256 || hex_data == new_hex_data) {
1485 g_warning("data format %s", strerror(errno));
1487 return EXIT_CODE_GENERIC;
1490 hex_data = new_hex_data;
1491 hex = g_ascii_strtoll(hex_data, &new_hex_data, 16);
1493 raw_length = hex + 3;
1494 } else if (hex == 0x02) {
1495 hex_data = new_hex_data;
1496 hex = g_ascii_strtoll(hex_data, &new_hex_data, 16);
1497 if (hex < 0 || hex >= 256 || hex_data == new_hex_data) {
1498 g_warning("data format %s", strerror(errno));
1500 return EXIT_CODE_GENERIC;
1503 hex_data = new_hex_data;
1504 hex = g_ascii_strtoll(hex_data, &new_hex_data, 16);
1505 if (hex < 0 || hex >= 256 || hex_data == new_hex_data) {
1506 g_warning("data format %s", strerror(errno));
1508 return EXIT_CODE_GENERIC;
1511 hex_data = new_hex_data;
1512 hex = g_ascii_strtoll(hex_data, &new_hex_data, 16);
1513 raw_length = hex + 5;
1515 hex_data = new_hex_data;
1516 hex = g_ascii_strtoll(hex_data, &new_hex_data, 16);
1517 raw_length += hex << 8;
1521 g_warning("bad raw stream");
1523 return EXIT_CODE_GENERIC;
1526 used_buffer_length += length;
1530 frame_length = raw_length * 3 + (raw_length / 20) * 4 + ((raw_length % 20) ? 2 : -2) + 29;
1532 if (used_buffer_length + length < frame_length) {
1533 used_buffer_length += length;
1537 if (8 == sscanf(data, "%04d-%02d-%02d %02d:%02d:%02d.%06d %c",
1538 &date.tm_year, &date.tm_mon, &date.tm_mday, &date.tm_hour,
1539 &date.tm_min, &date.tm_sec, &ms, &direction_character)) {
1541 g_debug("time %04d-%02d-%02d %02d:%02d:%02d.%06d %c",
1542 date.tm_year, date.tm_mon, date.tm_mday, date.tm_hour,
1543 date.tm_min, date.tm_sec, ms, direction_character);
1545 date.tm_year -= 1900;
1548 new_hex_data = data + 29;
1551 captured_length = 0;
1553 while ((long)(new_hex_data - data + sizeof(own_pcap_bluetooth_h4_header)) < frame_length) {
1554 hex_data = new_hex_data;
1555 hex = g_ascii_strtoll(hex_data, &new_hex_data, 16);
1557 packet[sizeof(own_pcap_bluetooth_h4_header) + captured_length] = (char) hex;
1558 captured_length += 1;
1561 h4_header->direction = GINT32_TO_BE(direction_character == '>');
1563 endless_loop = extcap_dumper_dump(extcap_dumper, fifo, packet,
1564 captured_length + sizeof(own_pcap_bluetooth_h4_header),
1565 captured_length + sizeof(own_pcap_bluetooth_h4_header),
1569 if (used_buffer_length + length >= frame_length) {
1570 memmove(data, data + frame_length, (size_t)(used_buffer_length + length - frame_length));
1571 used_buffer_length = (gssize)(used_buffer_length + length - frame_length);
1580 return EXIT_CODE_SUCCESS;
1583 /*----------------------------------------------------------------------------*/
1584 /* Android Bluetooth External Parser */
1585 /*----------------------------------------------------------------------------*/
1587 #define BLUEDROID_H4_PACKET_TYPE 0
1588 #define BLUEDROID_TIMESTAMP_SIZE 8
1589 #define BLUEDROID_H4_SIZE 1
1591 static const uint64_t BLUEDROID_TIMESTAMP_BASE = G_GUINT64_CONSTANT(0x00dcddb30f2f8000);
1593 #define BLUEDROID_H4_PACKET_TYPE_HCI_CMD 0x01
1594 #define BLUEDROID_H4_PACKET_TYPE_ACL 0x02
1595 #define BLUEDROID_H4_PACKET_TYPE_SCO 0x03
1596 #define BLUEDROID_H4_PACKET_TYPE_HCI_EVT 0x04
1598 #define BLUEDROID_DIRECTION_SENT 0
1599 #define BLUEDROID_DIRECTION_RECV 1
1601 static int adb_forward(char *serial_number, const char *adb_server_ip, unsigned short *adb_server_tcp_port,
1602 unsigned short local_tcp_port, unsigned short server_tcp_port) {
1603 socket_handle_t sock;
1605 static char helpful_packet[PACKET_LENGTH];
1606 static const char *adb_forward_template = "%s%s:forward:tcp:%05u;tcp:%05u";
1608 sock = adb_connect(adb_server_ip, adb_server_tcp_port);
1609 if (sock == INVALID_SOCKET)
1610 return EXIT_CODE_INVALID_SOCKET_5;
1612 result = g_snprintf(helpful_packet, PACKET_LENGTH, adb_forward_template, (serial_number) ? "host-serial:" : "host", (serial_number) ? serial_number: "", local_tcp_port, server_tcp_port);
1613 if (result <= 0 || result > PACKET_LENGTH) {
1614 g_warning("Error while completing adb packet");
1616 return EXIT_CODE_BAD_SIZE_OF_ASSEMBLED_ADB_PACKET_12;
1619 result = adb_send(sock, helpful_packet);
1625 static int capture_android_bluetooth_external_parser(char *interface,
1626 char *fifo, const char *adb_server_ip, unsigned short *adb_server_tcp_port,
1627 unsigned short *bt_server_tcp_port, unsigned int bt_forward_socket, const char *bt_local_ip,
1628 unsigned short *bt_local_tcp_port) {
1629 struct extcap_dumper extcap_dumper;
1630 static char buffer[PACKET_LENGTH];
1631 uint64_t *timestamp;
1632 char *packet = buffer + BLUEDROID_TIMESTAMP_SIZE - sizeof(own_pcap_bluetooth_h4_header); /* skip timestamp (8 bytes) and reuse its space for header */
1633 own_pcap_bluetooth_h4_header *h4_header;
1634 guint8 *payload = packet + sizeof(own_pcap_bluetooth_h4_header);
1635 const char *adb_tcp_bluedroid_external_parser_template = "tcp:%05u";
1638 gssize used_buffer_length = 0;
1640 socket_handle_t sock;
1641 struct sockaddr_in server;
1642 int captured_length;
1643 char *serial_number;
1644 static unsigned int id = 1;
1645 struct sockaddr_in client;
1647 SET_DATA(timestamp, value_u64, buffer);
1648 SET_DATA(h4_header, value_own_pcap_bluetooth_h4_header, packet);
1650 extcap_dumper = extcap_dumper_open(fifo, EXTCAP_ENCAP_BLUETOOTH_H4_WITH_PHDR);
1651 serial_number = get_serial_from_interface(interface);
1653 if (bt_forward_socket) {
1654 if ((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET) {
1655 g_warning("Cannot open system TCP socket: %s", strerror(errno));
1656 return EXIT_CODE_GENERIC;
1659 g_debug("Using config: Server TCP Port=%u, Local IP=%s, Local TCP Port=%u",
1660 *bt_server_tcp_port, bt_local_ip, *bt_local_tcp_port);
1662 if (*bt_local_tcp_port != 0) {
1665 result = adb_forward(serial_number, adb_server_ip, adb_server_tcp_port, *bt_local_tcp_port, *bt_server_tcp_port);
1666 g_debug("DO: adb forward tcp:%u (local) tcp:%u (remote) result=%i",
1667 *bt_local_tcp_port, *bt_server_tcp_port, result);
1670 memset(&server, 0 , sizeof(server));
1671 server.sin_family = AF_INET;
1672 server.sin_port = GINT16_TO_BE(*bt_local_tcp_port);
1673 ws_inet_pton4(bt_local_ip, &(server.sin_addr.s_addr));
1675 useSndTimeout(sock);
1677 if (connect(sock, (struct sockaddr *) &server, sizeof(server)) == SOCKET_ERROR) {
1678 g_warning("<%s> Please check that adb daemon is running.", strerror(errno));
1680 return EXIT_CODE_GENERIC;
1683 slen = (socklen_t)sizeof(client);
1684 if (getsockname(sock, (struct sockaddr *) &client, &slen)) {
1685 g_warning("getsockname: %s", strerror(errno));
1687 return EXIT_CODE_GENERIC;
1690 if (slen != sizeof(client)) {
1691 g_warning("incorrect length");
1693 return EXIT_CODE_GENERIC;
1696 g_debug("Client port %u", GUINT16_FROM_BE(client.sin_port));
1700 sock = adb_connect_transport(adb_server_ip, adb_server_tcp_port, serial_number);
1701 if (sock == INVALID_SOCKET)
1702 return EXIT_CODE_INVALID_SOCKET_6;
1704 result = g_snprintf((char *) buffer, PACKET_LENGTH, adb_tcp_bluedroid_external_parser_template, *bt_server_tcp_port);
1705 if (result <= 0 || result > PACKET_LENGTH) {
1706 g_warning("Error while completing adb packet");
1708 return EXIT_CODE_BAD_SIZE_OF_ASSEMBLED_ADB_PACKET_14;
1711 result = adb_send(sock, buffer);
1713 g_warning("Error while forwarding adb port");
1715 return EXIT_CODE_GENERIC;
1719 while (endless_loop) {
1721 length = recv(sock, buffer + used_buffer_length, (int)(PACKET_LENGTH - used_buffer_length), 0);
1723 #if EWOULDBLOCK != EAGAIN
1724 || errno == EWOULDBLOCK
1729 else if (errno != 0) {
1730 g_warning("ERROR capture: %s", strerror(errno));
1732 return EXIT_CODE_GENERIC;
1736 if (bt_forward_socket) {
1737 /* NOTE: Workaround... It seems that Bluedroid is slower and we can connect to socket that are not really ready... */
1738 g_warning("Broken socket connection. Try reconnect.");
1741 if ((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET) {
1742 g_warning("%s", strerror(errno));
1743 return EXIT_CODE_GENERIC;
1746 server.sin_family = AF_INET;
1747 server.sin_port = GINT16_TO_BE(*bt_local_tcp_port);
1748 ws_inet_pton4(bt_local_ip, &(server.sin_addr.s_addr));
1750 useSndTimeout(sock);
1752 if (connect(sock, (struct sockaddr *) &server, sizeof(server)) == SOCKET_ERROR) {
1753 g_warning("ERROR reconnect: <%s> Please check that adb daemon is running.", strerror(errno));
1755 return EXIT_CODE_GENERIC;
1758 g_warning("Broken socket connection.");
1760 return EXIT_CODE_GENERIC;
1766 used_buffer_length += length;
1768 g_debug("Received: length=%"G_GSSIZE_FORMAT"", length);
1770 while (((payload[BLUEDROID_H4_PACKET_TYPE] == BLUEDROID_H4_PACKET_TYPE_HCI_CMD || payload[BLUEDROID_H4_PACKET_TYPE] == BLUEDROID_H4_PACKET_TYPE_SCO) &&
1771 used_buffer_length >= BLUEDROID_TIMESTAMP_SIZE + BLUEDROID_H4_SIZE + 2 + 1 &&
1772 BLUEDROID_TIMESTAMP_SIZE + BLUEDROID_H4_SIZE + 2 + payload[BLUEDROID_H4_SIZE + 2] + 1 <= used_buffer_length) ||
1773 (payload[BLUEDROID_H4_PACKET_TYPE] == BLUEDROID_H4_PACKET_TYPE_ACL &&
1774 used_buffer_length >= BLUEDROID_TIMESTAMP_SIZE + BLUEDROID_H4_SIZE + 2 + 2 &&
1775 BLUEDROID_TIMESTAMP_SIZE + BLUEDROID_H4_SIZE + 2 + payload[BLUEDROID_H4_SIZE + 2] + (payload[BLUEDROID_H4_SIZE + 2 + 1] << 8) + 2 <= used_buffer_length) ||
1776 (payload[BLUEDROID_H4_PACKET_TYPE] == BLUEDROID_H4_PACKET_TYPE_SCO &&
1777 used_buffer_length >= BLUEDROID_TIMESTAMP_SIZE + BLUEDROID_H4_SIZE + 2 + 1 &&
1778 BLUEDROID_TIMESTAMP_SIZE + BLUEDROID_H4_SIZE + 2 + payload[BLUEDROID_H4_SIZE + 2] + 1 <= used_buffer_length) ||
1779 (payload[BLUEDROID_H4_PACKET_TYPE] == BLUEDROID_H4_PACKET_TYPE_HCI_EVT &&
1780 used_buffer_length >= BLUEDROID_TIMESTAMP_SIZE + BLUEDROID_H4_SIZE + 1 + 1 &&
1781 BLUEDROID_TIMESTAMP_SIZE + BLUEDROID_H4_SIZE + 1 + payload[BLUEDROID_H4_SIZE + 1] + 1 <= used_buffer_length)) {
1783 ts = GINT64_FROM_BE(*timestamp);
1785 switch (payload[BLUEDROID_H4_PACKET_TYPE]) {
1786 case BLUEDROID_H4_PACKET_TYPE_HCI_CMD:
1787 h4_header->direction = GINT32_TO_BE(BLUEDROID_DIRECTION_SENT);
1789 captured_length = (unsigned int)sizeof(own_pcap_bluetooth_h4_header) + payload[3] + 4;
1791 length = sizeof(own_pcap_bluetooth_h4_header) + BLUEDROID_H4_SIZE + 2 + 1 + payload[3];
1794 case BLUEDROID_H4_PACKET_TYPE_ACL:
1795 h4_header->direction = (payload[2] & 0x80) ? GINT32_TO_BE(BLUEDROID_DIRECTION_RECV) : GINT32_TO_BE(BLUEDROID_DIRECTION_SENT);
1797 captured_length = (unsigned int)sizeof(own_pcap_bluetooth_h4_header) + payload[3] + (payload[3 + 1] << 8) + 5;
1799 length = sizeof(own_pcap_bluetooth_h4_header) + BLUEDROID_H4_SIZE + 2 + 2 + payload[3] + (gssize)(payload[3 + 1] << 8);
1802 case BLUEDROID_H4_PACKET_TYPE_SCO:
1803 h4_header->direction = (payload[2] & 0x80) ? GINT32_TO_BE(BLUEDROID_DIRECTION_RECV) : GINT32_TO_BE(BLUEDROID_DIRECTION_SENT);
1805 captured_length = (unsigned int)sizeof(own_pcap_bluetooth_h4_header) + payload[3] + 4;
1807 length = sizeof(own_pcap_bluetooth_h4_header) + BLUEDROID_H4_SIZE + 2 + 1 + payload[3];
1810 case BLUEDROID_H4_PACKET_TYPE_HCI_EVT:
1811 h4_header->direction = GINT32_TO_BE(BLUEDROID_DIRECTION_RECV);
1813 captured_length = (unsigned int)sizeof(own_pcap_bluetooth_h4_header) + payload[2] + 3;
1815 length = sizeof(own_pcap_bluetooth_h4_header) + BLUEDROID_H4_SIZE + 1 + 1 + payload[2];
1819 g_warning("Invalid stream");
1821 return EXIT_CODE_GENERIC;
1824 g_debug("\t Packet %u: used_buffer_length=%"G_GSSIZE_FORMAT" length=%"G_GSSIZE_FORMAT" captured_length=%i type=0x%02x", id, used_buffer_length, length, captured_length, payload[BLUEDROID_H4_PACKET_TYPE]);
1825 if (payload[BLUEDROID_H4_PACKET_TYPE] == BLUEDROID_H4_PACKET_TYPE_HCI_EVT)
1826 g_debug("\t Packet: %02x %02x %02x", (unsigned int) payload[0], (unsigned int) payload[1], (unsigned int)payload[2]);
1829 ts -= BLUEDROID_TIMESTAMP_BASE;
1831 endless_loop = extcap_dumper_dump(extcap_dumper, fifo, packet,
1834 (uint32_t)(ts / 1000000),
1835 ((uint32_t)(ts % 1000000)) * 1000);
1837 used_buffer_length -= length - sizeof(own_pcap_bluetooth_h4_header) + BLUEDROID_TIMESTAMP_SIZE;
1838 if (used_buffer_length < 0) {
1839 g_warning("Internal Negative used buffer length.");
1841 return EXIT_CODE_GENERIC;
1843 memmove(buffer, packet + length, used_buffer_length);
1848 return EXIT_CODE_SUCCESS;
1851 /*----------------------------------------------------------------------------*/
1852 /* Android Btsnoop Net */
1853 /*----------------------------------------------------------------------------*/
1855 static int capture_android_bluetooth_btsnoop_net(char *interface, char *fifo,
1856 const char *adb_server_ip, unsigned short *adb_server_tcp_port) {
1857 struct extcap_dumper extcap_dumper;
1858 static char packet[PACKET_LENGTH];
1860 gssize used_buffer_length = 0;
1861 socket_handle_t sock;
1862 const char *adb_tcp_btsnoop_net = "tcp:8872";
1864 char *serial_number;
1866 static const uint64_t BTSNOOP_TIMESTAMP_BASE = G_GUINT64_CONSTANT(0x00dcddb30f2f8000);
1867 uint32_t *reported_length;
1868 uint32_t *captured_length;
1870 /* uint32_t *cumulative_dropped_packets; */
1871 uint64_t *timestamp;
1872 char *payload = packet + sizeof(own_pcap_bluetooth_h4_header) + 24;
1873 own_pcap_bluetooth_h4_header *h4_header;
1875 SET_DATA(reported_length, value_u32, packet + sizeof(own_pcap_bluetooth_h4_header) + 0);
1876 SET_DATA(captured_length, value_u32, packet + sizeof(own_pcap_bluetooth_h4_header) + 4);
1877 SET_DATA(flags, value_u32, packet + sizeof(own_pcap_bluetooth_h4_header) + 8);
1878 /* SET_DATA(cumulative_dropped_packets, value_u32, packet + sizeof(own_pcap_bluetooth_h4_header) + 12); */
1879 SET_DATA(timestamp, value_u64, packet + sizeof(own_pcap_bluetooth_h4_header) + 16);
1880 SET_DATA(h4_header, value_own_pcap_bluetooth_h4_header, payload - sizeof(own_pcap_bluetooth_h4_header));
1882 extcap_dumper = extcap_dumper_open(fifo, EXTCAP_ENCAP_BLUETOOTH_H4_WITH_PHDR);
1883 serial_number = get_serial_from_interface(interface);
1884 sock = adb_connect_transport(adb_server_ip, adb_server_tcp_port, serial_number);
1885 if (sock == INVALID_SOCKET)
1886 return EXIT_CODE_INVALID_SOCKET_7;
1888 result = adb_send(sock, adb_tcp_btsnoop_net);
1890 g_warning("Error while sending command <%s>", adb_tcp_btsnoop_net);
1892 return EXIT_CODE_ERROR_WHILE_SENDING_ADB_PACKET_2;
1895 /* Read "btsnoop" header - 16 bytes */
1896 while (used_buffer_length < 16) {
1897 length = recv(sock, packet + used_buffer_length, (int)(PACKET_LENGTH - used_buffer_length), 0);
1900 g_warning("Broken socket connection.");
1902 return EXIT_CODE_GENERIC;
1905 used_buffer_length += length;
1907 if (used_buffer_length > 16)
1908 memmove(packet, packet + 16, used_buffer_length - 16);
1910 used_buffer_length = 0;
1912 while (endless_loop) {
1914 length = recv(sock, packet + used_buffer_length + sizeof(own_pcap_bluetooth_h4_header),
1915 (int)(PACKET_LENGTH - sizeof(own_pcap_bluetooth_h4_header) - used_buffer_length), 0);
1917 #if EWOULDBLOCK != EAGAIN
1918 || errno == EWOULDBLOCK
1923 else if (errno != 0) {
1924 g_warning("ERROR capture: %s", strerror(errno));
1926 return EXIT_CODE_GENERIC;
1930 g_warning("Broken socket connection.");
1932 return EXIT_CODE_GENERIC;
1935 used_buffer_length += length;
1937 while (used_buffer_length >= 24 &&
1938 used_buffer_length >= (int) (24 + GINT32_FROM_BE(*captured_length))) {
1941 ts = GINT64_FROM_BE(*timestamp);
1942 ts -= BTSNOOP_TIMESTAMP_BASE;
1944 direction = GINT32_FROM_BE(*flags) & 0x01;
1945 h4_header->direction = GINT32_TO_BE(direction);
1947 endless_loop = extcap_dumper_dump(extcap_dumper, fifo,
1948 payload - sizeof(own_pcap_bluetooth_h4_header),
1949 GINT32_FROM_BE(*captured_length) + sizeof(own_pcap_bluetooth_h4_header),
1950 GINT32_FROM_BE(*reported_length) + sizeof(own_pcap_bluetooth_h4_header),
1951 (uint32_t)(ts / 1000000),
1952 ((uint32_t)(ts % 1000000)) * 1000);
1954 used_buffer_length -= 24 + GINT32_FROM_BE(*captured_length);
1955 if (used_buffer_length < 0) {
1956 g_warning("Internal Negative used buffer length.");
1958 return EXIT_CODE_GENERIC;
1961 if (used_buffer_length > 0)
1962 memmove(packet + sizeof(own_pcap_bluetooth_h4_header), payload + GINT32_FROM_BE(*captured_length), used_buffer_length);
1967 return EXIT_CODE_SUCCESS;
1970 /*----------------------------------------------------------------------------*/
1971 /* Android Logcat Text*/
1972 /*----------------------------------------------------------------------------*/
1975 static int capture_android_logcat_text(char *interface, char *fifo,
1976 const char *adb_server_ip, unsigned short *adb_server_tcp_port,
1977 int logcat_ignore_log_buffer, const char *logcat_custom_parameter) {
1978 struct extcap_dumper extcap_dumper;
1979 static char packet[PACKET_LENGTH];
1981 size_t used_buffer_length = 0;
1982 socket_handle_t sock;
1983 const char *protocol_name;
1984 size_t exported_pdu_headers_size = 0;
1985 struct exported_pdu_header exported_pdu_header_protocol_normal;
1986 struct exported_pdu_header *exported_pdu_header_protocol;
1987 struct exported_pdu_header exported_pdu_header_end = {0, 0};
1988 static const char *wireshark_protocol_logcat_text = "logcat_text_threadtime";
1989 const char *adb_logcat_template = "shell:export ANDROID_LOG_TAGS=\"\" ; exec logcat -v threadtime%s%s %s";
1990 char *serial_number = NULL;
1993 const char *logcat_buffer;
1994 const char *logcat_log_buffer;
1996 extcap_dumper = extcap_dumper_open(fifo, EXTCAP_ENCAP_WIRESHARK_UPPER_PDU);
1998 exported_pdu_header_protocol_normal.tag = GUINT16_TO_BE(WIRESHARK_UPPER_PDU_TAG_DISSECTOR_NAME);
1999 exported_pdu_header_protocol_normal.length = GUINT16_TO_BE(strlen(wireshark_protocol_logcat_text) + 2);
2001 serial_number = get_serial_from_interface(interface);
2002 sock = adb_connect_transport(adb_server_ip, adb_server_tcp_port, serial_number);
2003 if (sock == INVALID_SOCKET)
2004 return EXIT_CODE_INVALID_SOCKET_8;
2006 if (is_specified_interface(interface, INTERFACE_ANDROID_LOGCAT_MAIN) || is_specified_interface(interface, INTERFACE_ANDROID_LOGCAT_TEXT_MAIN))
2007 logcat_buffer = " -b main";
2008 else if (is_specified_interface(interface, INTERFACE_ANDROID_LOGCAT_SYSTEM) || is_specified_interface(interface, INTERFACE_ANDROID_LOGCAT_TEXT_SYSTEM))
2009 logcat_buffer = " -b system";
2010 else if (is_specified_interface(interface, INTERFACE_ANDROID_LOGCAT_RADIO) || is_specified_interface(interface, INTERFACE_ANDROID_LOGCAT_TEXT_RADIO))
2011 logcat_buffer = " -b radio";
2012 else if (is_specified_interface(interface, INTERFACE_ANDROID_LOGCAT_EVENTS) || is_specified_interface(interface, INTERFACE_ANDROID_LOGCAT_TEXT_EVENTS))
2013 logcat_buffer = " -b events";
2014 else if (is_specified_interface(interface, INTERFACE_ANDROID_LOGCAT_TEXT_CRASH))
2015 logcat_buffer = " -b crash";
2017 g_warning("Unknown interface: <%s>", interface);
2019 return EXIT_CODE_GENERIC;
2022 if (logcat_ignore_log_buffer)
2023 logcat_log_buffer = " -T 1";
2025 logcat_log_buffer = "";
2027 if (!logcat_custom_parameter)
2028 logcat_custom_parameter = "";
2030 result = g_snprintf((char *) packet, PACKET_LENGTH, adb_logcat_template, logcat_buffer, logcat_log_buffer, logcat_custom_parameter);
2031 if (result <= 0 || result > PACKET_LENGTH) {
2032 g_warning("Error while completing adb packet");
2034 return EXIT_CODE_BAD_SIZE_OF_ASSEMBLED_ADB_PACKET_17;
2037 result = adb_send(sock, packet);
2039 g_warning("Error while sending command <%s>", packet);
2041 return EXIT_CODE_ERROR_WHILE_SENDING_ADB_PACKET_3;
2044 protocol_name = wireshark_protocol_logcat_text;
2045 exported_pdu_header_protocol = &exported_pdu_header_protocol_normal;
2047 memcpy(packet, exported_pdu_header_protocol, sizeof(struct exported_pdu_header));
2048 exported_pdu_headers_size += sizeof(struct exported_pdu_header);
2050 memcpy(packet + exported_pdu_headers_size, protocol_name, GUINT16_FROM_BE(exported_pdu_header_protocol->length) - 2);
2051 exported_pdu_headers_size += GUINT16_FROM_BE(exported_pdu_header_protocol->length);
2053 packet[exported_pdu_headers_size - 1] = 0;
2054 packet[exported_pdu_headers_size - 2] = 0;
2056 memcpy(packet + exported_pdu_headers_size, &exported_pdu_header_end, sizeof(struct exported_pdu_header));
2057 exported_pdu_headers_size += sizeof(struct exported_pdu_header) + GUINT16_FROM_BE(exported_pdu_header_end.length);
2059 used_buffer_length = 0;
2060 while (endless_loop) {
2062 length = recv(sock, packet + exported_pdu_headers_size + used_buffer_length, (int)(PACKET_LENGTH - exported_pdu_headers_size - used_buffer_length), 0);
2064 #if EWOULDBLOCK != EAGAIN
2065 || errno == EWOULDBLOCK
2070 else if (errno != 0) {
2071 g_warning("ERROR capture: %s", strerror(errno));
2073 return EXIT_CODE_GENERIC;
2077 g_warning("Broken socket connection. Try reconnect.");
2079 return EXIT_CODE_GENERIC;
2082 used_buffer_length += length;
2084 while (used_buffer_length > 0 && (pos = (char *) memchr(packet + exported_pdu_headers_size, '\n', used_buffer_length))) {
2092 length = (gssize)(pos - packet) + 1;
2095 date = localtime(&t);
2098 if (6 == sscanf(packet + exported_pdu_headers_size, "%d-%d %d:%d:%d.%d", &date->tm_mon, &date->tm_mday, &date->tm_hour,
2099 &date->tm_min, &date->tm_sec, &ms)) {
2101 seconds = mktime(date);
2102 secs = (time_t) seconds;
2103 nsecs = (int) (ms * 1e6);
2106 endless_loop = extcap_dumper_dump(extcap_dumper, fifo, packet,
2111 memmove(packet + exported_pdu_headers_size, packet + length, used_buffer_length + exported_pdu_headers_size - length);
2112 used_buffer_length -= length - exported_pdu_headers_size;
2117 return EXIT_CODE_SUCCESS;
2120 /*----------------------------------------------------------------------------*/
2121 /* Android Logger / Logcat */
2122 /*----------------------------------------------------------------------------*/
2124 static int capture_android_logcat(char *interface, char *fifo,
2125 const char *adb_server_ip, unsigned short *adb_server_tcp_port) {
2126 struct extcap_dumper extcap_dumper;
2127 static char packet[PACKET_LENGTH];
2129 size_t used_buffer_length = 0;
2130 socket_handle_t sock;
2131 const char *protocol_name;
2132 size_t exported_pdu_headers_size = 0;
2133 struct exported_pdu_header exported_pdu_header_protocol_events;
2134 struct exported_pdu_header exported_pdu_header_protocol_normal;
2135 struct exported_pdu_header *exported_pdu_header_protocol;
2136 struct exported_pdu_header exported_pdu_header_end = {0, 0};
2137 static const char *wireshark_protocol_logcat = "logcat";
2138 static const char *wireshark_protocol_logcat_events = "logcat_events";
2139 const char *adb_command;
2140 uint16_t *payload_length;
2141 uint16_t *try_header_size;
2142 uint32_t *timestamp_secs;
2143 uint32_t *timestamp_nsecs;
2144 uint16_t header_size;
2146 char *serial_number = NULL;
2148 extcap_dumper = extcap_dumper_open(fifo, EXTCAP_ENCAP_WIRESHARK_UPPER_PDU);
2150 exported_pdu_header_protocol_events.tag = GUINT16_TO_BE(WIRESHARK_UPPER_PDU_TAG_DISSECTOR_NAME);
2151 exported_pdu_header_protocol_events.length = GUINT16_TO_BE(strlen(wireshark_protocol_logcat_events) + 2);
2153 exported_pdu_header_protocol_normal.tag = GUINT16_TO_BE(WIRESHARK_UPPER_PDU_TAG_DISSECTOR_NAME);
2154 exported_pdu_header_protocol_normal.length = GUINT16_TO_BE(strlen(wireshark_protocol_logcat) + 2);
2156 serial_number = get_serial_from_interface(interface);
2157 sock = adb_connect_transport(adb_server_ip, adb_server_tcp_port, serial_number);
2158 if (sock == INVALID_SOCKET)
2159 return EXIT_CODE_INVALID_SOCKET_9;
2161 adb_command = interface_to_logbuf(interface);
2163 g_warning("Unknown interface: <%s>", interface);
2165 return EXIT_CODE_GENERIC;
2168 result = adb_send(sock, adb_command);
2170 g_warning("Error while sending command <%s>", adb_command);
2172 return EXIT_CODE_ERROR_WHILE_SENDING_ADB_PACKET_4;
2175 if (is_specified_interface(interface, INTERFACE_ANDROID_LOGCAT_EVENTS))
2177 protocol_name = wireshark_protocol_logcat_events;
2178 exported_pdu_header_protocol = &exported_pdu_header_protocol_events;
2180 protocol_name = wireshark_protocol_logcat;
2181 exported_pdu_header_protocol = &exported_pdu_header_protocol_normal;
2184 memcpy(packet, exported_pdu_header_protocol, sizeof(struct exported_pdu_header));
2185 exported_pdu_headers_size += sizeof(struct exported_pdu_header);
2187 memcpy(packet + exported_pdu_headers_size, protocol_name, GUINT16_FROM_BE(exported_pdu_header_protocol->length) - 2);
2188 exported_pdu_headers_size += GUINT16_FROM_BE(exported_pdu_header_protocol->length);
2190 packet[exported_pdu_headers_size - 1] = 0;
2191 packet[exported_pdu_headers_size - 2] = 0;
2193 memcpy(packet + exported_pdu_headers_size, &exported_pdu_header_end, sizeof(struct exported_pdu_header));
2194 exported_pdu_headers_size += sizeof(struct exported_pdu_header) + GUINT16_FROM_BE(exported_pdu_header_end.length);
2196 SET_DATA(payload_length, value_u16, packet + exported_pdu_headers_size + 0);
2197 SET_DATA(try_header_size, value_u16, packet + exported_pdu_headers_size + 2);
2198 SET_DATA(timestamp_secs, value_u32, packet + exported_pdu_headers_size + 12);
2199 SET_DATA(timestamp_nsecs, value_u32, packet + exported_pdu_headers_size + 16);
2201 while (endless_loop) {
2203 length = recv(sock, packet + exported_pdu_headers_size + used_buffer_length, (int)(PACKET_LENGTH - exported_pdu_headers_size - used_buffer_length), 0);
2205 #if EWOULDBLOCK != EAGAIN
2206 || errno == EWOULDBLOCK
2211 else if (errno != 0) {
2212 g_warning("ERROR capture: %s", strerror(errno));
2214 return EXIT_CODE_GENERIC;
2218 while (endless_loop) {
2219 g_warning("Broken socket connection. Try reconnect.");
2220 used_buffer_length = 0;
2223 sock = adb_connect_transport(adb_server_ip, adb_server_tcp_port, serial_number);
2224 if (sock == INVALID_SOCKET)
2225 return EXIT_CODE_INVALID_SOCKET_10;
2227 result = adb_send(sock, adb_command);
2229 g_warning("WARNIG: Error while sending command <%s>", adb_command);
2237 used_buffer_length += length + exported_pdu_headers_size;
2239 if (*try_header_size != 24)
2242 header_size = *try_header_size;
2244 length = (*payload_length) + header_size + (gssize)exported_pdu_headers_size;
2246 while (used_buffer_length >= exported_pdu_headers_size + header_size && (size_t)length <= used_buffer_length) {
2247 endless_loop = extcap_dumper_dump(extcap_dumper, fifo, packet,
2250 *timestamp_secs, *timestamp_nsecs);
2252 memmove(packet + exported_pdu_headers_size, packet + length, used_buffer_length - length);
2253 used_buffer_length -= length;
2254 used_buffer_length += exported_pdu_headers_size;
2257 length = (*payload_length) + header_size + (gssize)exported_pdu_headers_size;
2259 if (*try_header_size != 24)
2262 header_size = *try_header_size;
2264 used_buffer_length -= exported_pdu_headers_size;
2269 return EXIT_CODE_SUCCESS;
2272 /* Translate tcpdump data link type strings to EXTCAP_ENCAP_ types
2273 * For info about available data link types see:
2274 * http://www.tcpdump.org/linktypes.html
2276 static int linktype_to_extcap_encap(const char* linktype)
2280 const char* const dlt;
2282 const struct dlt_encap lookup[] = {
2283 { EXTCAP_ENCAP_LINUX_SLL, "LINUX_SLL" },
2284 { EXTCAP_ENCAP_ETHERNET, "EN10MB" },
2285 { EXTCAP_ENCAP_IEEE802_11_RADIO, "IEEE802_11_RADIO" },
2286 { EXTCAP_ENCAP_NETLINK, "NETLINK" },
2290 int ret = EXTCAP_ENCAP_ETHERNET;
2294 for (i = 0; lookup[i].dlt; i++) {
2295 if (!strcmp(lookup[i].dlt, linktype)) {
2296 ret = lookup[i].extcap_encap;
2303 /*----------------------------------------------------------------------------*/
2304 /* Android Wifi Tcpdump */
2305 /* The Tcpdump sends data in pcap format. So for using the extcap_dumper we */
2306 /* need to unpack the pcap and then send the packet data to the dumper. */
2307 /*----------------------------------------------------------------------------*/
2308 static int capture_android_tcpdump(char *interface, char *fifo,
2309 const char *adb_server_ip, unsigned short *adb_server_tcp_port) {
2310 static const char *const adb_shell_tcpdump_format = "shell,raw:tcpdump -n -s 0 -u -i %s -w -";
2311 static const char *const adb_shell_legacy_tcpdump_format = "shell:tcpdump -n -s 0 -u -i %s -w -";
2312 static const char *const regex_interface = INTERFACE_ANDROID_TCPDUMP "-(?<iface>.*?)-(?<serial>.*)";
2313 static const char *const regex_linktype = "tcpdump: listening on .*?, link-type (?<linktype>.*?) ";
2314 struct extcap_dumper extcap_dumper;
2315 static char data[PACKET_LENGTH];
2317 gssize used_buffer_length = 0;
2318 gssize filter_buffer_length = 0;
2319 gssize frame_length=0;
2320 socket_handle_t sock;
2323 char *serial_number = NULL;
2324 static char filter_buffer[PACKET_LENGTH];
2325 gint device_endiness = G_LITTLE_ENDIAN;
2326 gboolean global_header_skipped=FALSE;
2327 pcaprec_hdr_t p_header;
2328 char *linktype = NULL;
2329 GRegex *regex = NULL;
2331 GMatchInfo *match = NULL;
2332 char tcpdump_cmd[80];
2333 gboolean pty_mode = FALSE;
2335 regex = g_regex_new(regex_interface, (GRegexCompileFlags)0, (GRegexMatchFlags)0, &err);
2337 g_warning("Failed to compile regex for tcpdump interface");
2338 return EXIT_CODE_GENERIC;
2341 g_regex_match(regex, interface, (GRegexMatchFlags)0, &match);
2342 if (!g_match_info_matches(match)) {
2343 g_warning("Failed to determine iface name and serial number");
2344 g_regex_unref(regex);
2345 return EXIT_CODE_GENERIC;
2348 iface = g_match_info_fetch_named(match, "iface");
2349 serial_number = g_match_info_fetch_named(match, "serial");
2350 g_match_info_free(match);
2351 g_regex_unref(regex);
2353 /* First check for the device if it is connected or not */
2354 sock = adb_connect_transport(adb_server_ip, adb_server_tcp_port, serial_number);
2355 if (sock == INVALID_SOCKET) {
2357 g_free(serial_number);
2358 return EXIT_CODE_INVALID_SOCKET_11;
2361 /* Try the new raw (non-PTY) shell protocol first */
2362 g_snprintf(tcpdump_cmd, sizeof(tcpdump_cmd), adb_shell_tcpdump_format, iface);
2363 result = adb_send(sock, tcpdump_cmd);
2365 g_debug("Target does not support raw shell protocol");
2368 /* Fall back to the old PTY shell */
2369 sock = adb_connect_transport(adb_server_ip, adb_server_tcp_port, serial_number);
2370 if (sock == INVALID_SOCKET) {
2372 g_free(serial_number);
2373 return EXIT_CODE_INVALID_SOCKET_12;
2377 g_snprintf(tcpdump_cmd, sizeof(tcpdump_cmd), adb_shell_legacy_tcpdump_format, iface);
2378 result = adb_send(sock, tcpdump_cmd);
2381 g_warning("Error while setting adb transport");
2383 return EXIT_CODE_GENERIC;
2387 g_free(serial_number);
2389 regex = g_regex_new(regex_linktype, (GRegexCompileFlags)0, (GRegexMatchFlags)0, &err);
2391 g_warning("Failed to compile regex for tcpdump data link type matching");
2393 return EXIT_CODE_GENERIC;
2396 while (endless_loop) {
2399 length = recv(sock, data + used_buffer_length, (int)(PACKET_LENGTH - used_buffer_length), 0);
2401 #if EWOULDBLOCK != EAGAIN
2402 || errno == EWOULDBLOCK
2407 else if (errno != 0) {
2408 g_warning("ERROR capture: %s", strerror(errno));
2410 g_regex_unref(regex);
2411 return EXIT_CODE_GENERIC;
2415 g_warning("Broken socket connection.");
2417 g_regex_unref(regex);
2418 return EXIT_CODE_GENERIC;
2421 used_buffer_length += length;
2424 * Checking for the starting for the pcap global header using the magic number
2426 if (used_buffer_length > 4) {
2427 guint * magic_number;
2428 magic_number= (guint *)data;
2429 if (*magic_number == 0xd4c3b2a1 || *magic_number == 0xa1b2c3d4) {
2430 if (data[0] == (char)0xd4){
2431 device_endiness = G_LITTLE_ENDIAN;
2434 device_endiness = G_BIG_ENDIAN;
2440 g_regex_match(regex, data, (GRegexMatchFlags)0, &match);
2441 if (g_match_info_matches(match)) {
2443 linktype = g_match_info_fetch_named(match, "linktype");
2445 g_match_info_free(match);
2446 i_position = (char *) memchr(data, '\n', used_buffer_length);
2447 if (i_position && i_position < data + used_buffer_length) {
2448 memmove(data, i_position + 1 , used_buffer_length - (i_position + 1 - data));
2449 used_buffer_length = used_buffer_length - (gssize) (i_position + 1 - data);
2452 g_regex_unref(regex);
2453 extcap_dumper = extcap_dumper_open(fifo, linktype_to_extcap_encap(linktype));
2456 filter_buffer_length=0;
2457 while (endless_loop) {
2458 gssize i = 0,read_offset,j=0;
2461 * Before Android 7 adb runs tcpdump in a shell/pseudoterminal and the PTY layer on the target converts
2462 * all \n to \r\n. In that case we need to undo this by changing all \r\n (0x0d0a) back to \n (0x0a).
2464 for (i = 0; i < (used_buffer_length - 1); i++) {
2465 if (pty_mode && data[i] == 0x0d && data[i + 1] == 0x0a) {
2468 filter_buffer[filter_buffer_length++] = data[i];
2471 /* Put the last characters in the start if it is still left in buffer.*/
2472 for (j=0; i < used_buffer_length; i++,j++) {
2475 used_buffer_length = j;
2476 if (global_header_skipped==FALSE && filter_buffer_length >= PCAP_GLOBAL_HEADER_LENGTH) {
2477 /*Skip the Global pcap header*/
2478 filter_buffer_length -= PCAP_GLOBAL_HEADER_LENGTH;
2480 /*Move the remaining content from start*/
2481 memmove(filter_buffer , filter_buffer + PCAP_GLOBAL_HEADER_LENGTH , filter_buffer_length);
2482 global_header_skipped = TRUE;
2484 else if (global_header_skipped && filter_buffer_length > PCAP_RECORD_HEADER_LENGTH) {
2486 while (filter_buffer_length > PCAP_RECORD_HEADER_LENGTH) {
2488 packet = filter_buffer + read_offset;
2490 * This fills the pcap header info based upon the endianess of the machine and android device.
2491 * If the endianess are different, pcap header bytes received from the android device are swapped
2492 * to be read properly by the machine else pcap header bytes are taken as it is.
2494 if (device_endiness == G_BYTE_ORDER) {
2495 p_header = *((pcaprec_hdr_t*)packet);
2498 p_header.ts_sec = GUINT32_SWAP_LE_BE(*((guint32*)packet));
2499 p_header.ts_usec = GUINT32_SWAP_LE_BE(*(guint32*)(packet +4));
2500 p_header.incl_len = GUINT32_SWAP_LE_BE(*(guint32*)(packet +8));
2501 p_header.orig_len = GUINT32_SWAP_LE_BE(*(guint32*)(packet +12));
2504 if ((gssize)(p_header.incl_len + PCAP_RECORD_HEADER_LENGTH) <= filter_buffer_length) {
2507 * It was observed that some times tcpdump reports the length of packet as '0' and that leads to the
2508 * ( Warn Error "Less data was read than was expected" while reading )
2509 * So to avoid this error we are checking for length of packet before passing it to dumper.
2511 if (p_header.incl_len > 0) {
2512 endless_loop = extcap_dumper_dump(extcap_dumper, fifo, filter_buffer + read_offset+ PCAP_RECORD_HEADER_LENGTH,
2513 p_header.incl_len , p_header.orig_len , p_header.ts_sec , p_header.ts_usec);
2515 frame_length = p_header.incl_len + PCAP_RECORD_HEADER_LENGTH;
2517 /*update the offset value for the next packet*/
2518 filter_buffer_length -= frame_length;
2519 read_offset += frame_length;
2522 /*The complete packet has not yet received*/
2526 if (read_offset!=0) {
2527 /*Move the rest of the filter data to the beginning of the filter_buffer */
2528 memmove(filter_buffer, filter_buffer + read_offset , filter_buffer_length);
2532 /*Get the data from the tcpdump process running in the android device*/
2533 while (endless_loop) {
2535 length = recv(sock, data + used_buffer_length, (int)(PACKET_LENGTH -(used_buffer_length + filter_buffer_length)), 0);
2537 #if EWOULDBLOCK != EAGAIN
2538 || errno == EWOULDBLOCK
2543 else if (errno != 0) {
2544 g_warning("ERROR capture: %s", strerror(errno));
2546 return EXIT_CODE_GENERIC;
2550 g_warning("Broken socket connection.");
2552 return EXIT_CODE_GENERIC;
2555 if ((used_buffer_length += length) > 1) {
2562 return EXIT_CODE_SUCCESS;
2565 int main(int argc, char **argv) {
2566 int ret = EXIT_CODE_GENERIC;
2569 const char *adb_server_ip = NULL;
2570 unsigned short *adb_server_tcp_port = NULL;
2571 unsigned int logcat_text = 0;
2572 unsigned int logcat_ignore_log_buffer = 0;
2573 const char *logcat_custom_parameter = NULL;
2574 const char *default_adb_server_ip = "127.0.0.1";
2575 unsigned short default_adb_server_tcp_port = 5037;
2576 unsigned short local_adb_server_tcp_port;
2577 unsigned short local_bt_server_tcp_port;
2578 unsigned short local_bt_local_tcp_port;
2579 unsigned short *bt_server_tcp_port = NULL;
2580 unsigned int bt_forward_socket = 0;
2581 const char *bt_local_ip = NULL;
2582 unsigned short *bt_local_tcp_port = NULL;
2583 unsigned short default_bt_server_tcp_port = 4330;
2584 const char *default_bt_local_ip = "127.0.0.1";
2585 unsigned short default_bt_local_tcp_port = 4330;
2586 extcap_parameters * extcap_conf = NULL;
2588 char *help_header = NULL;
2593 attach_parent_console();
2596 cmdarg_err_init(failure_warning_message, failure_warning_message);
2598 extcap_conf = g_new0(extcap_parameters, 1);
2600 help_url = data_file_url("androiddump.html");
2601 extcap_base_set_util_info(extcap_conf, argv[0], ANDROIDDUMP_VERSION_MAJOR, ANDROIDDUMP_VERSION_MINOR,
2602 ANDROIDDUMP_VERSION_RELEASE, help_url);
2605 help_header = g_strdup_printf(
2606 " %s --extcap-interfaces [--adb-server-ip=<arg>] [--adb-server-tcp-port=<arg>]\n"
2607 " %s --extcap-interface=INTERFACE --extcap-dlts\n"
2608 " %s --extcap-interface=INTERFACE --extcap-config\n"
2609 " %s --extcap-interface=INTERFACE --fifo=PATH_FILENAME --capture\n"
2610 "\nINTERFACE has the form TYPE-DEVICEID:\n"
2611 "\t""For example: "INTERFACE_ANDROID_BLUETOOTH_BTSNOOP_NET"-W3D7N15C29005648""\n"
2613 "\tTYPE is one of:\n"
2614 "\t"INTERFACE_ANDROID_LOGCAT_MAIN"\n"
2615 "\t"INTERFACE_ANDROID_LOGCAT_SYSTEM"\n"
2616 "\t"INTERFACE_ANDROID_LOGCAT_RADIO"\n"
2617 "\t"INTERFACE_ANDROID_LOGCAT_EVENTS"\n"
2618 "\t"INTERFACE_ANDROID_LOGCAT_TEXT_MAIN"\n"
2619 "\t"INTERFACE_ANDROID_LOGCAT_TEXT_SYSTEM"\n"
2620 "\t"INTERFACE_ANDROID_LOGCAT_TEXT_RADIO"\n"
2621 "\t"INTERFACE_ANDROID_LOGCAT_TEXT_EVENTS"\n"
2622 "\t"INTERFACE_ANDROID_LOGCAT_TEXT_CRASH"\n"
2623 "\t"INTERFACE_ANDROID_BLUETOOTH_HCIDUMP"\n"
2624 "\t"INTERFACE_ANDROID_BLUETOOTH_EXTERNAL_PARSER"\n"
2625 "\t"INTERFACE_ANDROID_BLUETOOTH_BTSNOOP_NET"\n"
2626 "\t"INTERFACE_ANDROID_TCPDUMP"\n"
2628 "\t""DEVICEID is the identifier of the device provided by Android SDK (see \"adb devices\")\n"
2629 "\t""For example: W3D7N15C29005648""\n",
2631 argv[0], argv[0], argv[0], argv[0]);
2632 extcap_help_add_header(extcap_conf, help_header);
2633 g_free(help_header);
2635 extcap_help_add_option(extcap_conf, "--help", "print this help");
2636 extcap_help_add_option(extcap_conf, "--adb-server-ip <IP>", "the IP address of the ADB server");
2637 extcap_help_add_option(extcap_conf, "--adb-server-tcp-port <port>", "the TCP port of the ADB server");
2638 extcap_help_add_option(extcap_conf, "--logcat-text", "use logcat text format");
2639 extcap_help_add_option(extcap_conf, "--logcat-ignore-log-buffer", "ignore log buffer");
2640 extcap_help_add_option(extcap_conf, "--logcat-custom-options <text>", "use custom logcat parameters");
2641 extcap_help_add_option(extcap_conf, "--bt-server-tcp-port <port>", "bluetooth server TCP port");
2642 extcap_help_add_option(extcap_conf, "--bt-forward-socket <path>", "bluetooth forward socket");
2643 extcap_help_add_option(extcap_conf, "--bt-local-ip <IP>", "the bluetooth local IP");
2644 extcap_help_add_option(extcap_conf, "--bt-local-tcp-port <port>", "the bluetooth local TCP port");
2650 extcap_help_print(extcap_conf);
2651 ret = EXIT_CODE_SUCCESS;
2655 while ((result = getopt_long(argc, argv, "", longopts, &option_idx)) != -1) {
2659 printf("%s\n", extcap_conf->version);
2660 ret = EXIT_CODE_SUCCESS;
2663 extcap_help_print(extcap_conf);
2664 ret = EXIT_CODE_SUCCESS;
2666 case OPT_CONFIG_ADB_SERVER_IP:
2667 adb_server_ip = optarg;
2669 case OPT_CONFIG_ADB_SERVER_TCP_PORT:
2670 adb_server_tcp_port = &local_adb_server_tcp_port;
2672 g_warning("Impossible exception. Parameter required argument, but there is no it right now.");
2675 if (!ws_strtou16(optarg, NULL, adb_server_tcp_port)) {
2676 g_warning("Invalid adb server TCP port: %s", optarg);
2680 case OPT_CONFIG_LOGCAT_TEXT:
2681 if (optarg && !*optarg)
2684 logcat_text = (g_ascii_strncasecmp(optarg, "TRUE", 4) == 0);
2686 case OPT_CONFIG_LOGCAT_IGNORE_LOG_BUFFER:
2687 if (optarg == NULL || (optarg && !*optarg))
2688 logcat_ignore_log_buffer = TRUE;
2690 logcat_ignore_log_buffer = (g_ascii_strncasecmp(optarg, "TRUE", 4) == 0);
2692 case OPT_CONFIG_LOGCAT_CUSTOM_OPTIONS:
2693 if (optarg == NULL || (optarg && *optarg == '\0')) {
2694 logcat_custom_parameter = NULL;
2698 if (g_regex_match_simple("(^|\\s)-[bBcDfgLnpPrv]", optarg, (GRegexCompileFlags)0, (GRegexMatchFlags)0)) {
2699 g_error("Found prohibited option in logcat-custom-options");
2700 return EXIT_CODE_GENERIC;
2703 logcat_custom_parameter = optarg;
2706 case OPT_CONFIG_BT_SERVER_TCP_PORT:
2707 bt_server_tcp_port = &local_bt_server_tcp_port;
2709 g_warning("Impossible exception. Parameter required argument, but there is no it right now.");
2712 if (!ws_strtou16(optarg, NULL, bt_server_tcp_port)) {
2713 g_warning("Invalid bluetooth server TCP port: %s", optarg);
2717 case OPT_CONFIG_BT_FORWARD_SOCKET:
2718 bt_forward_socket = (g_ascii_strncasecmp(optarg, "TRUE", 4) == 0);
2720 case OPT_CONFIG_BT_LOCAL_IP:
2721 bt_local_ip = optarg;
2723 case OPT_CONFIG_BT_LOCAL_TCP_PORT:
2724 bt_local_tcp_port = &local_bt_local_tcp_port;
2726 g_warning("Impossible exception. Parameter required argument, but there is no it right now.");
2729 if (!ws_strtou16(optarg, NULL, bt_local_tcp_port)) {
2730 g_warning("Invalid bluetooth local tcp port: %s", optarg);
2735 if (!extcap_base_parse_options(extcap_conf, result - EXTCAP_OPT_LIST_INTERFACES, optarg))
2737 g_warning("Invalid argument <%s>. Try --help.\n", argv[optind - 1]);
2744 adb_server_ip = default_adb_server_ip;
2746 if (!adb_server_tcp_port)
2747 adb_server_tcp_port = &default_adb_server_tcp_port;
2749 if (!bt_server_tcp_port)
2750 bt_server_tcp_port = &default_bt_server_tcp_port;
2753 bt_local_ip = default_bt_local_ip;
2755 if (!bt_local_tcp_port)
2756 bt_local_tcp_port = &default_bt_local_tcp_port;
2759 result = WSAStartup(MAKEWORD(1,1), &wsaData);
2761 g_warning("WSAStartup failed with %d", result);
2766 extcap_cmdline_debug(argv, argc);
2768 if (extcap_conf->do_list_interfaces)
2769 register_interfaces(extcap_conf, adb_server_ip, adb_server_tcp_port);
2772 * extcap implementation calls androiddump --extcap-dlts for each interface.
2773 * The only way to know whether an interface exists or not is to go through the
2774 * whole process of listing all interfaces (i.e. calling register_interfaces
2775 * function). Since being a system resource heavy operation and repeated for
2776 * each interface instead register a fake interface to be returned for dlt
2777 * listing only purpose
2779 if (extcap_conf->do_list_dlts) {
2780 new_fake_interface_for_list_dlts(extcap_conf, extcap_conf->interface);
2783 if (extcap_base_handle_interface(extcap_conf)) {
2784 ret = EXIT_CODE_SUCCESS;
2788 if (extcap_conf->show_config) {
2789 ret = list_config(extcap_conf->interface);
2793 if (extcap_conf->capture) {
2794 if (extcap_conf->interface && is_logcat_interface(extcap_conf->interface))
2796 ret = capture_android_logcat_text(extcap_conf->interface,
2797 extcap_conf->fifo, adb_server_ip, adb_server_tcp_port,
2798 logcat_ignore_log_buffer, logcat_custom_parameter);
2800 ret = capture_android_logcat(extcap_conf->interface,
2801 extcap_conf->fifo, adb_server_ip, adb_server_tcp_port);
2802 else if (extcap_conf->interface && is_logcat_text_interface(extcap_conf->interface))
2803 ret = capture_android_logcat_text(extcap_conf->interface,
2804 extcap_conf->fifo, adb_server_ip, adb_server_tcp_port,
2805 logcat_ignore_log_buffer, logcat_custom_parameter);
2806 else if (extcap_conf->interface && is_specified_interface(extcap_conf->interface, INTERFACE_ANDROID_BLUETOOTH_HCIDUMP))
2807 ret = capture_android_bluetooth_hcidump(extcap_conf->interface, extcap_conf->fifo, adb_server_ip, adb_server_tcp_port);
2808 else if (extcap_conf->interface && is_specified_interface(extcap_conf->interface, INTERFACE_ANDROID_BLUETOOTH_EXTERNAL_PARSER))
2809 ret = capture_android_bluetooth_external_parser(extcap_conf->interface, extcap_conf->fifo, adb_server_ip, adb_server_tcp_port,
2810 bt_server_tcp_port, bt_forward_socket, bt_local_ip, bt_local_tcp_port);
2811 else if (extcap_conf->interface && (is_specified_interface(extcap_conf->interface, INTERFACE_ANDROID_BLUETOOTH_BTSNOOP_NET)))
2812 ret = capture_android_bluetooth_btsnoop_net(extcap_conf->interface, extcap_conf->fifo, adb_server_ip, adb_server_tcp_port);
2813 else if (extcap_conf->interface && (is_specified_interface(extcap_conf->interface,INTERFACE_ANDROID_TCPDUMP)))
2814 ret = capture_android_tcpdump(extcap_conf->interface, extcap_conf->fifo, adb_server_ip, adb_server_tcp_port);
2819 /* no action was given, assume success */
2820 ret = EXIT_CODE_SUCCESS;
2823 /* clean up stuff */
2824 extcap_base_cleanup(&extcap_conf);
2825 #ifndef ANDROIDDUMP_USE_LIBPCAP
2834 WinMain (struct HINSTANCE__ *hInstance,
2835 struct HINSTANCE__ *hPrevInstance,
2839 return main(__argc, __argv);
2844 * Editor modelines - http://www.wireshark.org/tools/modelines.html
2849 * indent-tabs-mode: nil
2852 * vi: set shiftwidth=4 tabstop=8 expandtab:
2853 * :indentSize=4:tabSize=8:noTabs=true: