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-or-later
13 #define WS_LOG_DOMAIN "androiddump"
15 #include "extcap-base.h"
23 #include <wsutil/strtoi.h>
24 #include <wsutil/filesystem.h>
25 #include <wsutil/privileges.h>
26 #include <wsutil/please_report_bug.h>
27 #include <wsutil/wslog.h>
28 #include <wsutil/cmdarg_err.h>
29 #include <wsutil/inet_addr.h>
30 #include <wsutil/exported_pdu_tlvs.h>
32 #include "ui/failure_message.h"
34 #ifdef HAVE_NETINET_IN_H
35 # include <netinet/in.h>
42 #ifdef HAVE_SYS_SOCKET_H
43 #include <sys/socket.h>
46 #ifdef HAVE_ARPA_INET_H
47 #include <arpa/inet.h>
50 #ifdef HAVE_SYS_TIME_H
54 /* Configuration options */
55 /* #define ANDROIDDUMP_USE_LIBPCAP */
57 #define PCAP_GLOBAL_HEADER_LENGTH 24
58 #define PCAP_RECORD_HEADER_LENGTH 16
60 #ifdef ANDROIDDUMP_USE_LIBPCAP
63 #include <pcap/bluetooth.h>
65 #ifndef DLT_BLUETOOTH_H4_WITH_PHDR
66 #define DLT_BLUETOOTH_H4_WITH_PHDR 201
69 #ifndef DLT_WIRESHARK_UPPER_PDU
70 #define DLT_WIRESHARK_UPPER_PDU 252
73 #ifndef PCAP_TSTAMP_PRECISION_MICRO
74 #define PCAP_TSTAMP_PRECISION_MICRO 0
77 #ifndef PCAP_TSTAMP_PRECISION_NANO
78 #define PCAP_TSTAMP_PRECISION_NANO 1
81 #include "wiretap/wtap.h"
82 #include "wiretap/pcap-encap.h"
87 #ifdef ANDROIDDUMP_USE_LIBPCAP
88 #define EXTCAP_ENCAP_BLUETOOTH_H4_WITH_PHDR DLT_BLUETOOTH_H4_WITH_PHDR
89 #define EXTCAP_ENCAP_WIRESHARK_UPPER_PDU DLT_WIRESHARK_UPPER_PDU
90 #define EXTCAP_ENCAP_ETHERNET DLT_EN10MB
91 #define EXTCAP_ENCAP_LINUX_SLL DLT_LINUX_SLL
92 #define EXTCAP_ENCAP_IEEE802_11_RADIO DLT_IEEE802_11_RADIO
93 #define EXTCAP_ENCAP_NETLINK DLT_NETLINK
95 #define EXTCAP_ENCAP_BLUETOOTH_H4_WITH_PHDR WTAP_ENCAP_BLUETOOTH_H4_WITH_PHDR
96 #define EXTCAP_ENCAP_WIRESHARK_UPPER_PDU WTAP_ENCAP_WIRESHARK_UPPER_PDU
97 #define EXTCAP_ENCAP_ETHERNET WTAP_ENCAP_ETHERNET
98 #define EXTCAP_ENCAP_LINUX_SLL WTAP_ENCAP_SLL
99 #define EXTCAP_ENCAP_IEEE802_11_RADIO WTAP_ENCAP_IEEE_802_11_RADIOTAP
100 #define EXTCAP_ENCAP_NETLINK WTAP_ENCAP_NETLINK
103 #define INTERFACE_ANDROID_LOGCAT_MAIN "android-logcat-main"
104 #define INTERFACE_ANDROID_LOGCAT_SYSTEM "android-logcat-system"
105 #define INTERFACE_ANDROID_LOGCAT_RADIO "android-logcat-radio"
106 #define INTERFACE_ANDROID_LOGCAT_EVENTS "android-logcat-events"
107 #define INTERFACE_ANDROID_LOGCAT_TEXT_MAIN "android-logcat-text-main"
108 #define INTERFACE_ANDROID_LOGCAT_TEXT_SYSTEM "android-logcat-text-system"
109 #define INTERFACE_ANDROID_LOGCAT_TEXT_RADIO "android-logcat-text-radio"
110 #define INTERFACE_ANDROID_LOGCAT_TEXT_EVENTS "android-logcat-text-events"
111 #define INTERFACE_ANDROID_LOGCAT_TEXT_CRASH "android-logcat-text-crash"
112 #define INTERFACE_ANDROID_BLUETOOTH_HCIDUMP "android-bluetooth-hcidump"
113 #define INTERFACE_ANDROID_BLUETOOTH_EXTERNAL_PARSER "android-bluetooth-external-parser"
114 #define INTERFACE_ANDROID_BLUETOOTH_BTSNOOP_NET "android-bluetooth-btsnoop-net"
115 #define INTERFACE_ANDROID_TCPDUMP "android-tcpdump"
116 #define INTERFACE_ANDROID_TCPDUMP_FORMAT INTERFACE_ANDROID_TCPDUMP "-%s"
117 #define INTERFACE_ANDROID_TCPDUMP_SERIAL_FORMAT INTERFACE_ANDROID_TCPDUMP_FORMAT "-%s"
119 #define ANDROIDDUMP_VERSION_MAJOR "1"
120 #define ANDROIDDUMP_VERSION_MINOR "1"
121 #define ANDROIDDUMP_VERSION_RELEASE "0"
123 #define SERIAL_NUMBER_LENGTH_MAX 512
124 #define MODEL_NAME_LENGTH_MAX 64
126 #define PACKET_LENGTH 65535
128 #define SOCKET_RW_TIMEOUT_MS 2000
129 #define SOCKET_CONNECT_TIMEOUT_TRIES 10
130 #define SOCKET_CONNECT_DELAY_US 1000 /* (1000us = 1ms) * SOCKET_CONNECT_TIMEOUT_TRIES (10) = 10ms worst-case */
132 #define ADB_HEX4_FORMAT "%04zx"
133 #define ADB_HEX4_LEN 4
135 #define BTSNOOP_HDR_LEN 16
138 EXIT_CODE_SUCCESS
= 0,
139 EXIT_CODE_CANNOT_GET_INTERFACES_LIST
= 1,
140 EXIT_CODE_UNKNOWN_ENCAPSULATION_WIRETAP
,
141 EXIT_CODE_UNKNOWN_ENCAPSULATION_LIBPCAP
,
142 EXIT_CODE_CANNOT_SAVE_WIRETAP_DUMP
,
143 EXIT_CODE_CANNOT_SAVE_LIBPCAP_DUMP
,
144 EXIT_CODE_NO_INTERFACE_SPECIFIED
,
145 EXIT_CODE_INVALID_INTERFACE
,
146 EXIT_CODE_BAD_SIZE_OF_ASSEMBLED_ADB_PACKET_1
,
147 EXIT_CODE_BAD_SIZE_OF_ASSEMBLED_ADB_PACKET_2
,
148 EXIT_CODE_BAD_SIZE_OF_ASSEMBLED_ADB_PACKET_3
,
149 EXIT_CODE_BAD_SIZE_OF_ASSEMBLED_ADB_PACKET_4
,
150 EXIT_CODE_BAD_SIZE_OF_ASSEMBLED_ADB_PACKET_5
,
151 EXIT_CODE_BAD_SIZE_OF_ASSEMBLED_ADB_PACKET_6
,
152 EXIT_CODE_BAD_SIZE_OF_ASSEMBLED_ADB_PACKET_7
,
153 EXIT_CODE_BAD_SIZE_OF_ASSEMBLED_ADB_PACKET_8
,
154 EXIT_CODE_BAD_SIZE_OF_ASSEMBLED_ADB_PACKET_9
,
155 EXIT_CODE_BAD_SIZE_OF_ASSEMBLED_ADB_PACKET_10
,
156 EXIT_CODE_BAD_SIZE_OF_ASSEMBLED_ADB_PACKET_11
,
157 EXIT_CODE_BAD_SIZE_OF_ASSEMBLED_ADB_PACKET_12
,
158 EXIT_CODE_BAD_SIZE_OF_ASSEMBLED_ADB_PACKET_13
,
159 EXIT_CODE_BAD_SIZE_OF_ASSEMBLED_ADB_PACKET_14
,
160 EXIT_CODE_BAD_SIZE_OF_ASSEMBLED_ADB_PACKET_15
,
161 EXIT_CODE_BAD_SIZE_OF_ASSEMBLED_ADB_PACKET_16
,
162 EXIT_CODE_BAD_SIZE_OF_ASSEMBLED_ADB_PACKET_17
,
163 EXIT_CODE_BAD_SIZE_OF_ASSEMBLED_ADB_PACKET_18
,
164 EXIT_CODE_BAD_SIZE_OF_ASSEMBLED_ADB_PACKET_19
,
165 EXIT_CODE_BAD_SIZE_OF_ASSEMBLED_ADB_PACKET_20
,
166 EXIT_CODE_ERROR_WHILE_SENDING_ADB_PACKET_1
,
167 EXIT_CODE_ERROR_WHILE_SENDING_ADB_PACKET_2
,
168 EXIT_CODE_ERROR_WHILE_SENDING_ADB_PACKET_3
,
169 EXIT_CODE_ERROR_WHILE_SENDING_ADB_PACKET_4
,
170 EXIT_CODE_ERROR_WHILE_RECEIVING_ADB_PACKET_STATUS
,
171 EXIT_CODE_ERROR_WHILE_RECEIVING_ADB_PACKET_DATA
,
172 EXIT_CODE_INVALID_SOCKET_INTERFACES_LIST
,
173 EXIT_CODE_INVALID_SOCKET_1
,
174 EXIT_CODE_INVALID_SOCKET_2
,
175 EXIT_CODE_INVALID_SOCKET_3
,
176 EXIT_CODE_INVALID_SOCKET_4
,
177 EXIT_CODE_INVALID_SOCKET_5
,
178 EXIT_CODE_INVALID_SOCKET_6
,
179 EXIT_CODE_INVALID_SOCKET_7
,
180 EXIT_CODE_INVALID_SOCKET_8
,
181 EXIT_CODE_INVALID_SOCKET_9
,
182 EXIT_CODE_INVALID_SOCKET_10
,
183 EXIT_CODE_INVALID_SOCKET_11
,
184 EXIT_CODE_GENERIC
= -1
188 EXTCAP_BASE_OPTIONS_ENUM
,
191 OPT_CONFIG_ADB_SERVER_IP
,
192 OPT_CONFIG_ADB_SERVER_TCP_PORT
,
193 OPT_CONFIG_LOGCAT_TEXT
,
194 OPT_CONFIG_LOGCAT_IGNORE_LOG_BUFFER
,
195 OPT_CONFIG_LOGCAT_CUSTOM_OPTIONS
,
196 OPT_CONFIG_BT_SERVER_TCP_PORT
,
197 OPT_CONFIG_BT_FORWARD_SOCKET
,
198 OPT_CONFIG_BT_LOCAL_IP
,
199 OPT_CONFIG_BT_LOCAL_TCP_PORT
202 static const struct ws_option longopts
[] = {
204 { "help", ws_no_argument
, NULL
, OPT_HELP
},
205 { "version", ws_no_argument
, NULL
, OPT_VERSION
},
206 { "adb-server-ip", ws_required_argument
, NULL
, OPT_CONFIG_ADB_SERVER_IP
},
207 { "adb-server-tcp-port", ws_required_argument
, NULL
, OPT_CONFIG_ADB_SERVER_TCP_PORT
},
208 { "logcat-text", ws_optional_argument
, NULL
, OPT_CONFIG_LOGCAT_TEXT
},
209 { "logcat-ignore-log-buffer", ws_optional_argument
, NULL
, OPT_CONFIG_LOGCAT_IGNORE_LOG_BUFFER
},
210 { "logcat-custom-options", ws_required_argument
, NULL
, OPT_CONFIG_LOGCAT_CUSTOM_OPTIONS
},
211 { "bt-server-tcp-port", ws_required_argument
, NULL
, OPT_CONFIG_BT_SERVER_TCP_PORT
},
212 { "bt-forward-socket", ws_required_argument
, NULL
, OPT_CONFIG_BT_FORWARD_SOCKET
},
213 { "bt-local-ip", ws_required_argument
, NULL
, OPT_CONFIG_BT_LOCAL_IP
},
214 { "bt-local-tcp-port", ws_required_argument
, NULL
, OPT_CONFIG_BT_LOCAL_TCP_PORT
},
219 const char *display_name
;
220 const char *interface_name
;
221 struct interface_t
*next
;
224 struct exported_pdu_header
{
227 /* unsigned char value[0]; */
231 typedef struct _own_pcap_bluetooth_h4_header
{
233 } own_pcap_bluetooth_h4_header
;
235 typedef struct pcap_hdr_s
{
236 uint32_t magic_number
; /* magic number */
237 uint16_t version_major
; /* major version number */
238 uint16_t version_minor
; /* minor version number */
239 int32_t thiszone
; /* GMT to local correction */
240 uint32_t sigfigs
; /* accuracy of timestamps */
241 uint32_t snaplen
; /* max length of captured packets, in octets */
242 uint32_t network
; /* data link type */
246 typedef struct pcaprec_hdr_s
{
247 uint32_t ts_sec
; /* timestamp seconds */
248 uint32_t ts_usec
; /* timestamp microseconds */
249 uint32_t incl_len
; /* number of octets of packet saved in file */
250 uint32_t orig_len
; /* actual length of packet */
253 /* This fix compilator warning like "warning: cast from 'char *' to 'uint32_t *' (aka 'unsigned int *') increases required alignment from 1 to 4 " */
264 own_pcap_bluetooth_h4_header
*value_own_pcap_bluetooth_h4_header
;
267 #define SET_DATA(dest, type, src) \
269 data_aligned_t data_aligned; \
271 data_aligned.value_char = src; \
272 dest = data_aligned.type; \
275 struct extcap_dumper
{
278 #ifdef ANDROIDDUMP_USE_LIBPCAP
287 static int endless_loop
= 1;
290 static inline int is_specified_interface(const char *interface
, const char *interface_prefix
) {
291 return !strncmp(interface
, interface_prefix
, strlen(interface_prefix
));
294 static bool is_logcat_interface(const char *interface
) {
295 return is_specified_interface(interface
, INTERFACE_ANDROID_LOGCAT_MAIN
) ||
296 is_specified_interface(interface
, INTERFACE_ANDROID_LOGCAT_SYSTEM
) ||
297 is_specified_interface(interface
, INTERFACE_ANDROID_LOGCAT_RADIO
) ||
298 is_specified_interface(interface
, INTERFACE_ANDROID_LOGCAT_EVENTS
);
301 static bool is_logcat_text_interface(const char *interface
) {
302 return is_specified_interface(interface
, INTERFACE_ANDROID_LOGCAT_TEXT_MAIN
) ||
303 is_specified_interface(interface
, INTERFACE_ANDROID_LOGCAT_TEXT_SYSTEM
) ||
304 is_specified_interface(interface
, INTERFACE_ANDROID_LOGCAT_TEXT_RADIO
) ||
305 is_specified_interface(interface
, INTERFACE_ANDROID_LOGCAT_TEXT_EVENTS
) ||
306 is_specified_interface(interface
, INTERFACE_ANDROID_LOGCAT_TEXT_CRASH
);
309 static char* get_serial_from_interface(char *interface
)
311 static const char* const iface_prefix
[] = {
312 INTERFACE_ANDROID_LOGCAT_MAIN
,
313 INTERFACE_ANDROID_LOGCAT_SYSTEM
,
314 INTERFACE_ANDROID_LOGCAT_RADIO
,
315 INTERFACE_ANDROID_LOGCAT_EVENTS
,
316 INTERFACE_ANDROID_LOGCAT_TEXT_MAIN
,
317 INTERFACE_ANDROID_LOGCAT_TEXT_SYSTEM
,
318 INTERFACE_ANDROID_LOGCAT_TEXT_RADIO
,
319 INTERFACE_ANDROID_LOGCAT_TEXT_EVENTS
,
320 INTERFACE_ANDROID_LOGCAT_TEXT_CRASH
,
321 INTERFACE_ANDROID_BLUETOOTH_HCIDUMP
,
322 INTERFACE_ANDROID_BLUETOOTH_EXTERNAL_PARSER
,
323 INTERFACE_ANDROID_BLUETOOTH_BTSNOOP_NET
,
327 const char* curr
= NULL
;
328 for (i
= 0; (curr
= iface_prefix
[i
]); i
++) {
329 if (is_specified_interface(interface
, curr
) &&
330 strlen(interface
) > strlen(curr
) + 1) {
331 return interface
+ strlen(curr
) + 1;
337 static const char* interface_to_logbuf(char* interface
)
339 const char *const adb_log_main
= "log:main";
340 const char *const adb_log_system
= "log:system";
341 const char *const adb_log_radio
= "log:radio";
342 const char *const adb_log_events
= "log:events";
343 const char *logbuf
= NULL
;
345 if (is_specified_interface(interface
, INTERFACE_ANDROID_LOGCAT_MAIN
))
346 logbuf
= adb_log_main
;
347 else if (is_specified_interface(interface
, INTERFACE_ANDROID_LOGCAT_SYSTEM
))
348 logbuf
= adb_log_system
;
349 else if (is_specified_interface(interface
, INTERFACE_ANDROID_LOGCAT_RADIO
))
350 logbuf
= adb_log_radio
;
351 else if (is_specified_interface(interface
, INTERFACE_ANDROID_LOGCAT_EVENTS
))
352 logbuf
= adb_log_events
;
356 static void useSndTimeout(socket_handle_t sock
) {
359 const DWORD socket_timeout
= SOCKET_RW_TIMEOUT_MS
;
361 res
= setsockopt(sock
, SOL_SOCKET
, SO_SNDTIMEO
, (const char *) &socket_timeout
, (socklen_t
)sizeof(socket_timeout
));
363 const struct timeval socket_timeout
= {
364 .tv_sec
= SOCKET_RW_TIMEOUT_MS
/ 1000,
365 .tv_usec
= (SOCKET_RW_TIMEOUT_MS
% 1000) * 1000
368 res
= setsockopt(sock
, SOL_SOCKET
, SO_SNDTIMEO
, &socket_timeout
, (socklen_t
)sizeof(socket_timeout
));
371 ws_debug("Can't set socket timeout, using default");
374 static void useNonBlockingConnectTimeout(socket_handle_t sock
) {
376 unsigned long non_blocking
= 1;
378 /* set socket to non-blocking */
379 ioctlsocket(sock
, FIONBIO
, &non_blocking
);
381 int flags
= fcntl(sock
, F_GETFL
);
382 fcntl(sock
, F_SETFL
, flags
| O_NONBLOCK
);
386 static void useNormalConnectTimeout(socket_handle_t sock
) {
390 const DWORD socket_timeout
= SOCKET_RW_TIMEOUT_MS
;
391 unsigned long non_blocking
= 0;
393 res_snd
= setsockopt(sock
, SOL_SOCKET
, SO_SNDTIMEO
, (const char *) &socket_timeout
, sizeof(socket_timeout
));
394 res_rcv
= setsockopt(sock
, SOL_SOCKET
, SO_RCVTIMEO
, (const char *) &socket_timeout
, sizeof(socket_timeout
));
395 ioctlsocket(sock
, FIONBIO
, &non_blocking
);
397 int flags
= fcntl(sock
, F_GETFL
);
398 fcntl(sock
, F_SETFL
, flags
& ~O_NONBLOCK
);
399 const struct timeval socket_timeout
= {
400 .tv_sec
= SOCKET_RW_TIMEOUT_MS
/ 1000,
401 .tv_usec
= (SOCKET_RW_TIMEOUT_MS
% 1000) * 1000
404 res_snd
= setsockopt(sock
, SOL_SOCKET
, SO_SNDTIMEO
, &socket_timeout
, sizeof(socket_timeout
));
405 res_rcv
= setsockopt(sock
, SOL_SOCKET
, SO_RCVTIMEO
, &socket_timeout
, sizeof(socket_timeout
));
408 ws_debug("Can't set socket timeout, using default");
410 ws_debug("Can't set socket timeout, using default");
413 static struct extcap_dumper
extcap_dumper_open(char *fifo
, int encap
) {
414 struct extcap_dumper extcap_dumper
;
416 #ifdef ANDROIDDUMP_USE_LIBPCAP
419 pcap
= pcap_open_dead_with_tstamp_precision(encap
, PACKET_LENGTH
, PCAP_TSTAMP_PRECISION_NANO
);
420 extcap_dumper
.dumper
.pcap
= pcap_dump_open(pcap
, fifo
);
421 if (!extcap_dumper
.dumper
.pcap
) {
422 ws_warning("Can't open %s for saving packets: %s", fifo
, pcap_geterr(pcap
));
424 exit(EXIT_CODE_CANNOT_SAVE_LIBPCAP_DUMP
);
426 extcap_dumper
.encap
= encap
;
427 if (pcap_dump_flush(extcap_dumper
.dumper
.pcap
) == -1) {
428 ws_warning("Write to %s failed: %s", fifo
, g_strerror(errno
));
431 wtap_dump_params params
= WTAP_DUMP_PARAMS_INIT
;
432 int file_type_subtype
;
434 char *err_info
= NULL
;
438 params
.encap
= encap
;
439 params
.snaplen
= PACKET_LENGTH
;
440 file_type_subtype
= wtap_pcap_nsec_file_type_subtype();
441 extcap_dumper
.dumper
.wtap
= wtap_dump_open(fifo
, file_type_subtype
, WTAP_UNCOMPRESSED
, ¶ms
, &err
, &err_info
);
442 if (!extcap_dumper
.dumper
.wtap
) {
443 cfile_dump_open_failure_message(fifo
, err
, err_info
, file_type_subtype
);
444 exit(EXIT_CODE_CANNOT_SAVE_WIRETAP_DUMP
);
446 extcap_dumper
.encap
= encap
;
447 if (!wtap_dump_flush(extcap_dumper
.dumper
.wtap
, &err
)) {
448 cfile_dump_open_failure_message(fifo
, err
, NULL
, file_type_subtype
);
449 exit(EXIT_CODE_CANNOT_SAVE_WIRETAP_DUMP
);
453 return extcap_dumper
;
456 static bool extcap_dumper_dump(struct extcap_dumper extcap_dumper
,
457 char *fifo
, char *buffer
,
458 ssize_t captured_length
, ssize_t reported_length
,
459 time_t seconds
, int nanoseconds
) {
460 #ifdef ANDROIDDUMP_USE_LIBPCAP
461 struct pcap_pkthdr pcap_header
;
463 pcap_header
.caplen
= (bpf_u_int32
) captured_length
;
464 pcap_header
.len
= (bpf_u_int32
) reported_length
;
465 pcap_header
.ts
.tv_sec
= seconds
;
466 pcap_header
.ts
.tv_usec
= nanoseconds
/ 1000;
468 pcap_dump((u_char
*) extcap_dumper
.dumper
.pcap
, &pcap_header
, buffer
);
469 if (pcap_dump_flush(extcap_dumper
.dumper
.pcap
) == -1) {
470 ws_warning("Write to %s failed: %s", fifo
, g_strerror(errno
));
477 rec
.rec_type
= REC_TYPE_PACKET
;
478 rec
.presence_flags
= WTAP_HAS_TS
;
479 rec
.rec_header
.packet_header
.caplen
= (uint32_t) captured_length
;
480 rec
.rec_header
.packet_header
.len
= (uint32_t) reported_length
;
482 rec
.ts
.secs
= seconds
;
483 rec
.ts
.nsecs
= (int) nanoseconds
;
487 /* NOTE: Try to handle pseudoheaders manually */
488 if (extcap_dumper
.encap
== EXTCAP_ENCAP_BLUETOOTH_H4_WITH_PHDR
) {
491 SET_DATA(direction
, value_u32
, buffer
)
493 rec
.rec_header
.packet_header
.pseudo_header
.bthci
.sent
= GINT32_FROM_BE(*direction
) ? 0 : 1;
495 rec
.rec_header
.packet_header
.len
-= (uint32_t)sizeof(own_pcap_bluetooth_h4_header
);
496 rec
.rec_header
.packet_header
.caplen
-= (uint32_t)sizeof(own_pcap_bluetooth_h4_header
);
498 buffer
+= sizeof(own_pcap_bluetooth_h4_header
);
500 rec
.rec_header
.packet_header
.pkt_encap
= extcap_dumper
.encap
;
502 if (!wtap_dump(extcap_dumper
.dumper
.wtap
, &rec
, (const uint8_t *) buffer
, &err
, &err_info
)) {
503 cfile_write_failure_message(NULL
, fifo
, err
, err_info
, 0,
504 wtap_dump_file_type_subtype(extcap_dumper
.dumper
.wtap
));
508 if (!wtap_dump_flush(extcap_dumper
.dumper
.wtap
, &err
)) {
509 cfile_write_failure_message(NULL
, fifo
, err
, NULL
, 0,
510 wtap_dump_file_type_subtype(extcap_dumper
.dumper
.wtap
));
519 static socket_handle_t
adb_connect(const char *server_ip
, unsigned short *server_tcp_port
) {
520 socket_handle_t sock
;
522 struct sockaddr_in server
;
523 struct sockaddr_in client
;
530 memset(&server
, 0x0, sizeof(server
));
532 server
.sin_family
= AF_INET
;
533 server
.sin_port
= GINT16_TO_BE(*server_tcp_port
);
534 ws_inet_pton4(server_ip
, (ws_in4_addr
*)&(server
.sin_addr
.s_addr
));
536 if ((sock
= socket(AF_INET
, SOCK_STREAM
, IPPROTO_TCP
)) == INVALID_SOCKET
) {
537 ws_warning("Cannot open system TCP socket: %s", strerror(errno
));
538 return INVALID_SOCKET
;
541 useNonBlockingConnectTimeout(sock
);
542 status
= connect(sock
, (struct sockaddr
*) &server
, (socklen_t
)sizeof(server
));
544 if ((status
== SOCKET_ERROR
) && (WSAGetLastError() == WSAEWOULDBLOCK
)) {
546 if ((status
== SOCKET_ERROR
) && (errno
== EINPROGRESS
)) {
548 while (tries
< SOCKET_CONNECT_TIMEOUT_TRIES
) {
550 struct timeval timeout
= {
552 .tv_usec
= SOCKET_CONNECT_DELAY_US
,
556 FD_SET(sock
, &fdset
);
558 if ((select(0, NULL
, &fdset
, NULL
, &timeout
) != 0) && (FD_ISSET(sock
, &fdset
))) {
562 if ((select(sock
+1, NULL
, &fdset
, NULL
, &timeout
) != 0) && (FD_ISSET(sock
, &fdset
))) {
563 length
= sizeof(result
);
564 getsockopt(sock
, SOL_SOCKET
, SO_ERROR
, &result
, &length
);
568 ws_debug("Error connecting to ADB: <%s>", strerror(result
));
573 ws_debug("Try %i: Timeout connecting to ADB", tries
);
577 useNormalConnectTimeout(sock
);
579 if (status
== SOCKET_ERROR
) {
581 /* NOTE: This does not work well - make significant delay while initializing Wireshark.
582 Do fork() then call "adb" also does not make sense, because there is need to
583 do something like sleep(1) to ensure adb is started... system() cannot be used
584 on Windows, because open console window. This helper does not work as expected,
585 so disable it and user must ensure that adb is started (adb start-server,
586 but also all other command start-server automatically)
589 if (_execlp("adb", "adb", "start-server", NULL
)) {
591 if (execlp("adb", "adb", "start-server", NULL
)) {
593 errmsg("WARNING: Cannot execute system command to start adb: %s", strerror(errno
));
595 return INVALID_SOCKET
;
598 if (connect(sock
, (struct sockaddr
*) &server
, (socklen_t
)sizeof(server
)) == SOCKET_ERROR
) {
599 ws_warning("Cannot connect to ADB: <%s> Please check that adb daemon is running.", strerror(errno
));
601 return INVALID_SOCKET
;
604 ws_debug("Cannot connect to ADB: Please check that adb daemon is running.");
606 return INVALID_SOCKET
;
610 length
= sizeof(client
);
611 if (getsockname(sock
, (struct sockaddr
*) &client
, &length
)) {
612 ws_warning("getsockname: %s", strerror(errno
));
614 return INVALID_SOCKET
;
617 if (length
!= sizeof(client
)) {
618 ws_warning("incorrect length");
620 return INVALID_SOCKET
;
623 ws_debug("Client port %u", GUINT16_FROM_BE(client
.sin_port
));
629 static char *adb_send_and_receive(socket_handle_t sock
, const char *adb_service
,
630 char *buffer
, size_t buffer_length
, size_t *data_length
) {
631 size_t used_buffer_length
;
632 size_t bytes_to_read
;
637 size_t adb_service_length
;
639 adb_service_length
= strlen(adb_service
);
640 if (adb_service_length
> INT_MAX
) {
641 ws_warning("Service name too long when sending <%s> to ADB daemon", adb_service
);
647 /* 8 bytes of hex length + terminating NUL */
648 if (buffer_length
< 9) {
649 ws_warning("Buffer for response too short while sending <%s> to ADB daemon", adb_service
);
655 snprintf(buffer
, buffer_length
, ADB_HEX4_FORMAT
, adb_service_length
);
656 result
= send(sock
, buffer
, ADB_HEX4_LEN
, 0);
657 if (result
< ADB_HEX4_LEN
) {
658 ws_warning("Error while sending <%s> length to ADB daemon", adb_service
);
662 result
= send(sock
, adb_service
, (int) adb_service_length
, 0);
663 if (result
!= (ssize_t
) adb_service_length
) {
664 ws_warning("Error while sending <%s> to ADB daemon", adb_service
);
670 used_buffer_length
= 0;
671 while (used_buffer_length
< 8) {
672 bytes_to_read
= buffer_length
- used_buffer_length
;
673 if (bytes_to_read
> INT_MAX
)
674 bytes_to_read
= INT_MAX
;
675 result
= recv(sock
, buffer
+ used_buffer_length
, (int)bytes_to_read
, 0);
678 ws_warning("Broken socket connection while fetching reply status for <%s>", adb_service
);
684 used_buffer_length
+= result
;
687 memcpy(status
, buffer
, 4);
688 tmp_buffer
= buffer
[8];
690 if (!ws_hexstrtou32(buffer
+ 4, NULL
, &length
)) {
691 ws_warning("Invalid reply length <%s> while reading reply for <%s>", buffer
+ 4, adb_service
);
696 buffer
[8] = tmp_buffer
;
698 if (buffer_length
< length
+ 8) {
699 ws_warning("Buffer for response too short while sending <%s> to ADB daemon", adb_service
);
705 while (used_buffer_length
< length
+ 8) {
706 bytes_to_read
= buffer_length
- used_buffer_length
;
707 if (bytes_to_read
> INT_MAX
)
708 bytes_to_read
= INT_MAX
;
709 result
= recv(sock
, buffer
+ used_buffer_length
, (int)bytes_to_read
, 0);
712 ws_warning("Broken socket connection while reading reply for <%s>", adb_service
);
718 used_buffer_length
+= result
;
722 *data_length
= used_buffer_length
- 8;
724 if (memcmp(status
, "OKAY", 4)) {
725 ws_warning("Error while receiving by ADB for <%s>", adb_service
);
735 static char *adb_send_and_read(socket_handle_t sock
, const char *adb_service
, char *buffer
,
736 int buffer_length
, ssize_t
*data_length
) {
737 ssize_t used_buffer_length
;
740 size_t adb_service_length
;
742 adb_service_length
= strlen(adb_service
);
743 snprintf(buffer
, buffer_length
, ADB_HEX4_FORMAT
, adb_service_length
);
745 result
= send(sock
, buffer
, ADB_HEX4_LEN
, 0);
746 if (result
< ADB_HEX4_LEN
) {
747 ws_warning("Error while sending <%s> to ADB daemon", adb_service
);
751 result
= send(sock
, adb_service
, (int) adb_service_length
, 0);
752 if (result
!= (ssize_t
) adb_service_length
) {
753 ws_warning("Error while sending <%s> to ADB", adb_service
);
759 used_buffer_length
= 0;
760 while (used_buffer_length
< 4) {
761 result
= recv(sock
, buffer
+ used_buffer_length
, (int)(buffer_length
- used_buffer_length
), 0);
764 ws_warning("Broken socket connection while fetching reply status for <%s>", adb_service
);
769 used_buffer_length
+= result
;
772 memcpy(status
, buffer
, 4);
775 result
= recv(sock
, buffer
+ used_buffer_length
, (int)(buffer_length
- used_buffer_length
), 0);
778 ws_warning("Broken socket connection while reading reply for <%s>", adb_service
);
781 } else if (result
== 0) {
785 used_buffer_length
+= result
;
789 *data_length
= used_buffer_length
- 4;
791 if (memcmp(status
, "OKAY", 4)) {
792 ws_warning("Error while receiving by ADB for <%s>", adb_service
);
802 static int adb_send(socket_handle_t sock
, const char *adb_service
) {
804 int used_buffer_length
;
806 size_t adb_service_length
;
808 adb_service_length
= strlen(adb_service
);
809 result
= snprintf(buffer
, sizeof(buffer
), ADB_HEX4_FORMAT
, adb_service_length
);
810 if ((size_t)result
>= sizeof(buffer
)) {
811 /* Truncation (or failure somehow) */
812 ws_warning("Service name too long when sending <%s> to ADB daemon", adb_service
);
813 return EXIT_CODE_ERROR_WHILE_SENDING_ADB_PACKET_1
;
816 result
= send(sock
, buffer
, ADB_HEX4_LEN
, 0);
817 if (result
< ADB_HEX4_LEN
) {
818 ws_warning("Error while sending <%s> to ADB daemon", adb_service
);
819 return EXIT_CODE_ERROR_WHILE_SENDING_ADB_PACKET_1
;
822 result
= send(sock
, adb_service
, (int) adb_service_length
, 0);
823 if (result
!= (ssize_t
) adb_service_length
) {
824 ws_warning("Error while sending <%s> to ADB", adb_service
);
825 return EXIT_CODE_ERROR_WHILE_SENDING_ADB_PACKET_1
;
828 used_buffer_length
= 0;
829 while (used_buffer_length
< 4) {
830 result
= recv(sock
, buffer
+ used_buffer_length
, 4 - used_buffer_length
, 0);
833 ws_warning("Broken socket connection while fetching reply status for <%s>", adb_service
);
835 return EXIT_CODE_ERROR_WHILE_RECEIVING_ADB_PACKET_STATUS
;
838 used_buffer_length
+= (int)result
;
841 if (memcmp(buffer
, "OKAY", 4)) {
842 ws_debug("Error while receiving by ADB for <%s>", adb_service
);
844 return EXIT_CODE_ERROR_WHILE_RECEIVING_ADB_PACKET_DATA
;
847 return EXIT_CODE_SUCCESS
;
851 static socket_handle_t
852 adb_connect_transport(const char *server_ip
, unsigned short *server_tcp_port
,
853 const char* serial_number
)
855 static const char *const adb_transport_serial_templace
= "host:transport:%s";
856 static const char *const adb_transport_any
= "host:transport-any";
857 char transport_buf
[80];
858 const char* transport
= transport_buf
;
859 socket_handle_t sock
;
862 sock
= adb_connect(server_ip
, server_tcp_port
);
863 if (sock
== INVALID_SOCKET
) {
864 ws_warning("Error while connecting to adb server");
868 if (!serial_number
) {
869 transport
= adb_transport_any
;
871 result
= snprintf(transport_buf
, sizeof(transport_buf
), adb_transport_serial_templace
, serial_number
);
872 if (result
<= 0 || result
> (int)sizeof(transport_buf
)) {
873 ws_warning("Error while completing adb packet for transport");
875 return INVALID_SOCKET
;
879 result
= adb_send(sock
, transport
);
881 ws_warning("Error while setting adb transport for <%s>", transport_buf
);
883 return INVALID_SOCKET
;
889 static void new_interface(extcap_parameters
* extcap_conf
, const char *interface_id
,
890 const char *model_name
, const char *serial_number
, const char *display_name
)
892 char *interface
= ws_strdup_printf("%s-%s", interface_id
, serial_number
);
893 char *ifdisplay
= ws_strdup_printf("%s %s %s", display_name
, model_name
, serial_number
);
895 if (is_specified_interface(interface
, INTERFACE_ANDROID_BLUETOOTH_HCIDUMP
) ||
896 is_specified_interface(interface
, INTERFACE_ANDROID_BLUETOOTH_EXTERNAL_PARSER
) ||
897 is_specified_interface(interface
, INTERFACE_ANDROID_BLUETOOTH_BTSNOOP_NET
)) {
899 extcap_base_register_interface_ext(extcap_conf
, interface
, ifdisplay
, 99, "BluetoothH4", "Bluetooth HCI UART transport layer plus pseudo-header" );
900 } else if (is_logcat_interface(interface
) || is_logcat_text_interface(interface
)) {
901 extcap_base_register_interface(extcap_conf
, interface
, ifdisplay
, 252, "Upper PDU" );
902 } else if (is_specified_interface(interface
, INTERFACE_ANDROID_TCPDUMP
)) {
903 extcap_base_register_interface(extcap_conf
, interface
, ifdisplay
, 1, "Ethernet");
910 static void new_fake_interface_for_list_dlts(extcap_parameters
* extcap_conf
,
913 if (is_specified_interface(ifname
, INTERFACE_ANDROID_BLUETOOTH_HCIDUMP
) ||
914 is_specified_interface(ifname
, INTERFACE_ANDROID_BLUETOOTH_EXTERNAL_PARSER
) ||
915 is_specified_interface(ifname
, INTERFACE_ANDROID_BLUETOOTH_BTSNOOP_NET
)) {
916 extcap_base_register_interface_ext(extcap_conf
, ifname
, ifname
, 99, "BluetoothH4", "Bluetooth HCI UART transport layer plus pseudo-header" );
917 } else if (is_logcat_interface(ifname
) || is_logcat_text_interface(ifname
)) {
918 extcap_base_register_interface(extcap_conf
, ifname
, ifname
, 252, "Upper PDU" );
919 } else if (is_specified_interface(ifname
, INTERFACE_ANDROID_TCPDUMP
)) {
920 extcap_base_register_interface(extcap_conf
, ifname
, ifname
, 1, "Ethernet");
925 static int add_tcpdump_interfaces(extcap_parameters
* extcap_conf
, const char *adb_server_ip
, unsigned short *adb_server_tcp_port
, const char *serial_number
)
927 static const char *const adb_tcpdump_list
= "shell:tcpdump -D";
928 static const char *const regex_ifaces
= "\\d+\\.(?<iface>\\S+)(\\s+?(?:(?:\\(.*\\))*)(\\s*?\\[(?<flags>.*?)\\])?)?";
929 static char recv_buffer
[PACKET_LENGTH
];
932 socket_handle_t sock
;
933 GRegex
* regex
= NULL
;
935 GMatchInfo
*match
= NULL
;
938 bool flags_supported
;
940 sock
= adb_connect_transport(adb_server_ip
, adb_server_tcp_port
, serial_number
);
941 if (sock
== INVALID_SOCKET
) {
942 ws_warning("Failed to connect to adb server");
943 return EXIT_CODE_GENERIC
;
946 response
= adb_send_and_read(sock
, adb_tcpdump_list
, recv_buffer
, sizeof(recv_buffer
), &data_length
);
950 ws_warning("Failed to get list of available tcpdump interfaces");
951 return EXIT_CODE_GENERIC
;
953 response
[data_length
] = '\0';
955 regex
= g_regex_new(regex_ifaces
, G_REGEX_RAW
, (GRegexMatchFlags
)0, &err
);
957 ws_warning("Failed to compile regex for tcpdump interface matching");
958 return EXIT_CODE_GENERIC
;
961 flags_supported
= (strstr(response
, "[") != 0) && (strstr(response
, "]") != 0);
963 tok
= strtok(response
, "\n");
964 while (tok
!= NULL
) {
965 g_regex_match(regex
, tok
, (GRegexMatchFlags
)0, &match
);
966 if (g_match_info_matches(match
)) {
967 char *iface
= g_match_info_fetch_named(match
, "iface");
968 char *flags
= g_match_info_fetch_named(match
, "flags");
970 if (!flags_supported
|| (flags
&& strstr(flags
, "Up"))) {
971 snprintf(iface_name
, sizeof(iface_name
), INTERFACE_ANDROID_TCPDUMP_FORMAT
, iface
);
972 new_interface(extcap_conf
, iface_name
, iface
, serial_number
, "Android tcpdump");
977 g_match_info_free(match
);
978 tok
= strtok(NULL
, "\n");
980 g_regex_unref(regex
);
985 static int register_interfaces(extcap_parameters
* extcap_conf
, const char *adb_server_ip
, unsigned short *adb_server_tcp_port
) {
986 static char packet
[PACKET_LENGTH
];
987 static char helpful_packet
[PACKET_LENGTH
];
988 char check_port_buf
[80];
992 size_t device_length
;
993 socket_handle_t sock
;
994 const char *adb_check_port_templace
= "shell:cat /proc/%s/net/tcp";
995 const char *adb_devices
= "host:devices-l";
996 const char *adb_api_level
= "shell:getprop ro.build.version.sdk";
997 const char *adb_hcidump_version
= "shell:hcidump --version";
998 const char *adb_ps_droid_bluetooth
= "shell:ps droid.bluetooth";
999 const char *adb_ps_bluetooth_app
= "shell:ps com.android.bluetooth";
1000 const char *adb_ps_with_grep
= "shell:ps | grep com.android.bluetooth";
1001 const char *adb_ps_all_with_grep
= "shell:ps -A | grep com.*android.bluetooth";
1002 char serial_number
[SERIAL_NUMBER_LENGTH_MAX
];
1003 char model_name
[MODEL_NAME_LENGTH_MAX
];
1011 int disable_interface
;
1013 /* NOTE: It seems that "adb devices" and "adb shell" closed connection
1014 so cannot send next command after them, there is need to reconnect */
1016 sock
= adb_connect(adb_server_ip
, adb_server_tcp_port
);
1017 if (sock
== INVALID_SOCKET
)
1018 return EXIT_CODE_INVALID_SOCKET_INTERFACES_LIST
;
1020 device_list
= adb_send_and_receive(sock
, adb_devices
, packet
, sizeof(packet
), &device_length
);
1024 ws_warning("Cannot get list of interfaces from devices");
1026 return EXIT_CODE_CANNOT_GET_INTERFACES_LIST
;
1029 device_list
[device_length
] = '\0';
1030 pos
= (char *) device_list
;
1032 while (pos
< (char *) (device_list
+ device_length
)) {
1034 pos
= strchr(pos
, ' ');
1036 result
= (int) (pos
- prev_pos
);
1037 pos
= strchr(pos
, '\n') + 1;
1038 if (result
>= (int) sizeof(serial_number
)) {
1039 ws_warning("Serial number too long, ignore device");
1042 memcpy(serial_number
, prev_pos
, result
);
1043 serial_number
[result
] = '\0';
1045 model_name
[0] = '\0';
1046 model_pos
= g_strstr_len(i_pos
, pos
- i_pos
, "model:");
1048 device_pos
= g_strstr_len(i_pos
, pos
- i_pos
, "device:");
1049 if (device_pos
&& device_pos
- model_pos
- 6 - 1 < MODEL_NAME_LENGTH_MAX
) {
1050 memcpy(model_name
, model_pos
+ 6, device_pos
- model_pos
- 6 - 1);
1051 model_name
[device_pos
- model_pos
- 6 - 1] = '\0';
1055 if (model_name
[0] == '\0')
1056 strcpy(model_name
, "unknown");
1058 ws_debug("Processing device: \"%s\" <%s>" , serial_number
, model_name
);
1060 /* Function will only add tcpdump interfaces if tcpdump is present on the device */
1061 result
= add_tcpdump_interfaces(extcap_conf
, adb_server_ip
, adb_server_tcp_port
, serial_number
);
1063 ws_warning("Error while adding tcpdump interfaces");
1066 sock
= adb_connect_transport(adb_server_ip
, adb_server_tcp_port
, serial_number
);
1067 if (sock
== INVALID_SOCKET
) continue;
1069 response
= adb_send_and_read(sock
, adb_api_level
, helpful_packet
, sizeof(helpful_packet
), &data_length
);
1073 ws_warning("Error on socket: <%s>", helpful_packet
);
1077 response
[data_length
] = '\0';
1078 api_level
= (int) g_ascii_strtoll(response
, NULL
, 10);
1079 ws_debug("Android API Level for %s is %i", serial_number
, api_level
);
1081 if (api_level
< 21) {
1082 new_interface(extcap_conf
, INTERFACE_ANDROID_LOGCAT_MAIN
, model_name
, serial_number
, "Android Logcat Main");
1083 new_interface(extcap_conf
, INTERFACE_ANDROID_LOGCAT_SYSTEM
, model_name
, serial_number
, "Android Logcat System");
1084 new_interface(extcap_conf
, INTERFACE_ANDROID_LOGCAT_RADIO
, model_name
, serial_number
, "Android Logcat Radio");
1085 new_interface(extcap_conf
, INTERFACE_ANDROID_LOGCAT_EVENTS
, model_name
, serial_number
, "Android Logcat Events");
1087 new_interface(extcap_conf
, INTERFACE_ANDROID_LOGCAT_TEXT_MAIN
, model_name
, serial_number
, "Android Logcat Main");
1088 new_interface(extcap_conf
, INTERFACE_ANDROID_LOGCAT_TEXT_SYSTEM
, model_name
, serial_number
, "Android Logcat System");
1089 new_interface(extcap_conf
, INTERFACE_ANDROID_LOGCAT_TEXT_RADIO
, model_name
, serial_number
, "Android Logcat Radio");
1090 new_interface(extcap_conf
, INTERFACE_ANDROID_LOGCAT_TEXT_EVENTS
, model_name
, serial_number
, "Android Logcat Events");
1092 new_interface(extcap_conf
, INTERFACE_ANDROID_LOGCAT_TEXT_MAIN
, model_name
, serial_number
, "Android Logcat Main");
1093 new_interface(extcap_conf
, INTERFACE_ANDROID_LOGCAT_TEXT_SYSTEM
, model_name
, serial_number
, "Android Logcat System");
1094 new_interface(extcap_conf
, INTERFACE_ANDROID_LOGCAT_TEXT_RADIO
, model_name
, serial_number
, "Android Logcat Radio");
1095 new_interface(extcap_conf
, INTERFACE_ANDROID_LOGCAT_TEXT_EVENTS
, model_name
, serial_number
, "Android Logcat Events");
1096 new_interface(extcap_conf
, INTERFACE_ANDROID_LOGCAT_TEXT_CRASH
, model_name
, serial_number
, "Android Logcat Crash");
1099 if (api_level
>= 5 && api_level
< 17) {
1100 disable_interface
= 0;
1102 sock
= adb_connect_transport(adb_server_ip
, adb_server_tcp_port
, serial_number
);
1103 if (sock
== INVALID_SOCKET
) continue;
1105 response
= adb_send_and_read(sock
, adb_hcidump_version
, helpful_packet
, sizeof(helpful_packet
), &data_length
);
1108 if (!response
|| data_length
< 1) {
1109 ws_warning("Error while getting hcidump version by <%s> (%p len=%"PRIdMAX
")",
1110 adb_hcidump_version
, (void*)response
, (intmax_t)data_length
);
1111 ws_debug("Android hcidump version for %s is unknown", serial_number
);
1112 disable_interface
= 1;
1114 response
[data_length
] = '\0';
1116 if (g_ascii_strtoull(response
, NULL
, 10) == 0) {
1117 ws_debug("Android hcidump version for %s is unknown", serial_number
);
1118 disable_interface
= 1;
1120 ws_debug("Android hcidump version for %s is %s", serial_number
, response
);
1124 if (!disable_interface
) {
1125 new_interface(extcap_conf
, INTERFACE_ANDROID_BLUETOOTH_HCIDUMP
, model_name
, serial_number
, "Android Bluetooth Hcidump");
1129 if (api_level
>= 17 && api_level
< 21) {
1130 disable_interface
= 0;
1131 sock
= adb_connect_transport(adb_server_ip
, adb_server_tcp_port
, serial_number
);
1132 if (sock
== INVALID_SOCKET
) continue;
1134 response
= adb_send_and_read(sock
, adb_ps_droid_bluetooth
, helpful_packet
, sizeof(helpful_packet
), &data_length
);
1136 if (!response
|| data_length
< 1) {
1137 ws_warning("Error while getting Bluetooth application process id by <%s> "
1138 "(%p len=%"PRIdMAX
")", adb_ps_droid_bluetooth
, (void*)response
, (intmax_t)data_length
);
1139 ws_debug( "Android Bluetooth application PID for %s is unknown", serial_number
);
1140 disable_interface
= 1;
1145 memset(pid
, 0, sizeof(pid
));
1146 response
[data_length
] = '\0';
1148 data_str
= strchr(response
, '\n');
1149 if (data_str
&& sscanf(data_str
, "%*s %15s", pid
) == 1) {
1150 ws_debug("Android Bluetooth application PID for %s is %s", serial_number
, pid
);
1152 result
= snprintf(check_port_buf
, sizeof(check_port_buf
), adb_check_port_templace
, pid
);
1153 if (result
<= 0 || result
> (int)sizeof(check_port_buf
)) {
1154 ws_warning("Error while completing adb packet");
1155 return EXIT_CODE_BAD_SIZE_OF_ASSEMBLED_ADB_PACKET_6
;
1158 sock
= adb_connect_transport(adb_server_ip
, adb_server_tcp_port
, serial_number
);
1159 if (sock
== INVALID_SOCKET
) continue;
1161 response
= adb_send_and_read(sock
, check_port_buf
, helpful_packet
, sizeof(helpful_packet
), &data_length
);
1165 disable_interface
= 1;
1167 response
[data_length
] = '\0';
1169 data_str
= strchr(response
, '\n');
1170 if (data_str
&& sscanf(data_str
, "%*s %15s", pid
) == 1 && strlen(pid
) > 10 && strcmp(pid
+ 9, "10EA") == 0) {
1171 ws_debug("Bluedroid External Parser Port for %s is %s", serial_number
, pid
+ 9);
1173 disable_interface
= 1;
1174 ws_debug("Bluedroid External Parser Port for %s is unknown", serial_number
);
1178 disable_interface
= 1;
1179 ws_debug("Android Bluetooth application PID for %s is unknown", serial_number
);
1183 if (!disable_interface
) {
1184 new_interface(extcap_conf
, INTERFACE_ANDROID_BLUETOOTH_EXTERNAL_PARSER
, model_name
, serial_number
, "Android Bluetooth External Parser");
1188 if (api_level
>= 21) {
1190 disable_interface
= 0;
1192 if (api_level
>= 26) {
1193 ps_cmd
= adb_ps_all_with_grep
;
1194 } else if (api_level
>= 24) {
1195 ps_cmd
= adb_ps_with_grep
;
1196 } else if (api_level
>= 23) {
1197 ps_cmd
= adb_ps_bluetooth_app
;
1199 ps_cmd
= adb_ps_droid_bluetooth
;
1201 sock
= adb_connect_transport(adb_server_ip
, adb_server_tcp_port
, serial_number
);
1202 if (sock
== INVALID_SOCKET
) continue;
1204 response
= adb_send_and_read(sock
, ps_cmd
, helpful_packet
, sizeof(helpful_packet
), &data_length
);
1207 if (!response
|| data_length
< 1) {
1208 ws_warning("Error while getting Bluetooth application process id by <%s> "
1209 "(%p len=%"PRIdMAX
")", ps_cmd
, (void*)response
, (intmax_t)data_length
);
1210 ws_debug("Android Bluetooth application PID for %s is unknown", serial_number
);
1211 disable_interface
= 1;
1216 memset(pid
, 0, sizeof(pid
));
1217 response
[data_length
] = '\0';
1219 if (api_level
>= 24)
1220 data_str
= response
;
1222 data_str
= strchr(response
, '\n');
1224 if (data_str
&& sscanf(data_str
, "%*s %15s", pid
) == 1) {
1225 ws_debug("Android Bluetooth application PID for %s is %s", serial_number
, pid
);
1227 result
= snprintf(check_port_buf
, sizeof(check_port_buf
), adb_check_port_templace
, pid
);
1228 if (result
<= 0 || result
> (int)sizeof(check_port_buf
)) {
1229 ws_warning("Error while completing adb packet");
1230 return EXIT_CODE_BAD_SIZE_OF_ASSEMBLED_ADB_PACKET_9
;
1233 sock
= adb_connect_transport(adb_server_ip
, adb_server_tcp_port
, serial_number
);
1234 if (sock
== INVALID_SOCKET
) continue;
1236 response
= adb_send_and_read(sock
, check_port_buf
, helpful_packet
, sizeof(helpful_packet
), &data_length
);
1240 disable_interface
= 1;
1242 response
[data_length
] = '\0';
1243 data_str
= strtok(response
, "\n");
1244 while (data_str
!= NULL
) {
1245 if (sscanf(data_str
, "%*s %15s", pid
) == 1 && strlen(pid
) > 10 && strcmp(pid
+ 9, "22A8") == 0) {
1246 ws_debug("Btsnoop Net Port for %s is %s", serial_number
, pid
+ 9);
1249 data_str
= strtok(NULL
, "\n");
1251 if (data_str
== NULL
) {
1252 disable_interface
= 1;
1253 ws_debug("Btsnoop Net Port for %s is unknown", serial_number
);
1257 disable_interface
= 1;
1258 ws_debug("Android Bluetooth application PID for %s is unknown", serial_number
);
1262 if (!disable_interface
) {
1263 new_interface(extcap_conf
, INTERFACE_ANDROID_BLUETOOTH_BTSNOOP_NET
, model_name
, serial_number
, "Android Bluetooth Btsnoop Net");
1268 return EXIT_CODE_SUCCESS
;
1271 static int list_config(char *interface
) {
1272 int ret
= EXIT_CODE_INVALID_INTERFACE
;
1276 ws_warning("No interface specified.");
1277 return EXIT_CODE_NO_INTERFACE_SPECIFIED
;
1280 if (is_specified_interface(interface
, INTERFACE_ANDROID_BLUETOOTH_EXTERNAL_PARSER
)) {
1281 printf("arg {number=%u}{call=--adb-server-ip}{display=ADB Server IP Address}{type=string}{default=127.0.0.1}\n", inc
++);
1282 printf("arg {number=%u}{call=--adb-server-tcp-port}{display=ADB Server TCP Port}{type=integer}{range=0,65535}{default=5037}\n", inc
++);
1283 printf("arg {number=%u}{call=--bt-server-tcp-port}{display=Bluetooth Server TCP Port}{type=integer}{range=0,65535}{default=4330}\n", inc
++);
1284 printf("arg {number=%u}{call=--bt-forward-socket}{display=Forward Bluetooth Socket}{type=boolean}{default=false}\n", inc
++);
1285 printf("arg {number=%u}{call=--bt-local-ip}{display=Bluetooth Local IP Address}{type=string}{default=127.0.0.1}\n", inc
++);
1286 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
++);
1287 ret
= EXIT_CODE_SUCCESS
;
1288 } else if (is_specified_interface(interface
, INTERFACE_ANDROID_BLUETOOTH_HCIDUMP
) ||
1289 is_specified_interface(interface
, INTERFACE_ANDROID_BLUETOOTH_BTSNOOP_NET
) ||
1290 is_specified_interface(interface
, INTERFACE_ANDROID_TCPDUMP
)) {
1291 printf("arg {number=%u}{call=--adb-server-ip}{display=ADB Server IP Address}{type=string}{default=127.0.0.1}\n", inc
++);
1292 printf("arg {number=%u}{call=--adb-server-tcp-port}{display=ADB Server TCP Port}{type=integer}{range=0,65535}{default=5037}\n", inc
++);
1293 ret
= EXIT_CODE_SUCCESS
;
1294 } else if (is_logcat_interface(interface
)) {
1295 printf("arg {number=%u}{call=--adb-server-ip}{display=ADB Server IP Address}{type=string}{default=127.0.0.1}\n", inc
++);
1296 printf("arg {number=%u}{call=--adb-server-tcp-port}{display=ADB Server TCP Port}{type=integer}{range=0,65535}{default=5037}\n", inc
++);
1297 printf("arg {number=%u}{call=--logcat-text}{display=Use text logcat}{type=boolean}{default=false}\n", inc
++);
1298 printf("arg {number=%u}{call=--logcat-ignore-log-buffer}{display=Ignore log buffer}{type=boolean}{default=false}\n", inc
++);
1299 printf("arg {number=%u}{call=--logcat-custom-options}{display=Custom logcat parameters}{type=string}\n", inc
++);
1300 ret
= EXIT_CODE_SUCCESS
;
1301 } else if (is_logcat_text_interface(interface
)) {
1302 printf("arg {number=%u}{call=--adb-server-ip}{display=ADB Server IP Address}{type=string}{default=127.0.0.1}\n", inc
++);
1303 printf("arg {number=%u}{call=--adb-server-tcp-port}{display=ADB Server TCP Port}{type=integer}{range=0,65535}{default=5037}\n", inc
++);
1304 printf("arg {number=%u}{call=--logcat-ignore-log-buffer}{display=Ignore log buffer}{type=boolean}{default=false}\n", inc
++);
1305 printf("arg {number=%u}{call=--logcat-custom-options}{display=Custom logcat parameters}{type=string}\n", inc
++);
1306 ret
= EXIT_CODE_SUCCESS
;
1309 if (ret
!= EXIT_CODE_SUCCESS
)
1310 ws_warning("Invalid interface: <%s>", interface
);
1312 extcap_config_debug(&inc
);
1317 /*----------------------------------------------------------------------------*/
1318 /* Android Bluetooth Hcidump */
1319 /*----------------------------------------------------------------------------*/
1321 static int capture_android_bluetooth_hcidump(char *interface
, char *fifo
,
1322 const char *adb_server_ip
, unsigned short *adb_server_tcp_port
) {
1323 struct extcap_dumper extcap_dumper
;
1324 static char data
[PACKET_LENGTH
];
1325 static char packet
[PACKET_LENGTH
];
1327 ssize_t used_buffer_length
= 0;
1328 socket_handle_t sock
= INVALID_SOCKET
;
1329 const char *adb_shell_hcidump
= "shell:hcidump -R -t";
1330 const char *adb_shell_su_hcidump
= "shell:su -c hcidump -R -t";
1332 char *serial_number
;
1334 unsigned int captured_length
;
1338 own_pcap_bluetooth_h4_header
*h4_header
;
1339 int64_t raw_length
= 0;
1340 int64_t frame_length
;
1343 char direction_character
;
1345 SET_DATA(h4_header
, value_own_pcap_bluetooth_h4_header
, packet
);
1347 extcap_dumper
= extcap_dumper_open(fifo
, EXTCAP_ENCAP_BLUETOOTH_H4_WITH_PHDR
);
1349 serial_number
= get_serial_from_interface(interface
);
1350 sock
= adb_connect_transport(adb_server_ip
, adb_server_tcp_port
, serial_number
);
1351 if (sock
== INVALID_SOCKET
)
1352 return EXIT_CODE_INVALID_SOCKET_3
;
1354 result
= adb_send(sock
, adb_shell_hcidump
);
1356 ws_warning("Error while starting capture by sending command: %s", adb_shell_hcidump
);
1358 return EXIT_CODE_GENERIC
;
1361 while (endless_loop
) {
1365 length
= recv(sock
, data
+ used_buffer_length
, (int)(PACKET_LENGTH
- used_buffer_length
), 0);
1367 #if EWOULDBLOCK != EAGAIN
1368 || errno
== EWOULDBLOCK
1373 else if (errno
!= 0) {
1374 ws_warning("ERROR capture: %s", strerror(errno
));
1376 return EXIT_CODE_GENERIC
;
1380 ws_warning("Broken socket connection.");
1382 return EXIT_CODE_GENERIC
;
1385 used_buffer_length
+= length
;
1386 i_position
= (char *) memchr(data
, '\n', used_buffer_length
);
1387 if (i_position
&& i_position
< data
+ used_buffer_length
) {
1388 char *state_line_position
= i_position
+ 1;
1390 if (!strncmp(data
, "/system/bin/sh: hcidump: not found", 34)) {
1391 ws_warning("Command not found for <%s>", adb_shell_hcidump
);
1393 return EXIT_CODE_GENERIC
;
1396 i_position
= (char *) memchr(i_position
+ 1, '\n', used_buffer_length
);
1399 if (!strncmp(state_line_position
, "Can't access device: Permission denied", 38)) {
1400 ws_warning("No permission for command <%s>", adb_shell_hcidump
);
1401 used_buffer_length
= 0;
1403 sock
= INVALID_SOCKET
;
1406 memmove(data
, i_position
, used_buffer_length
- (i_position
- data
));
1407 used_buffer_length
= used_buffer_length
- (ssize_t
)(i_position
- data
);
1413 if (sock
== INVALID_SOCKET
) {
1414 sock
= adb_connect_transport(adb_server_ip
, adb_server_tcp_port
, serial_number
);
1415 if (sock
== INVALID_SOCKET
)
1416 return EXIT_CODE_INVALID_SOCKET_4
;
1418 result
= adb_send(sock
, adb_shell_su_hcidump
);
1420 ws_warning("Error while starting capture by sending command: <%s>", adb_shell_su_hcidump
);
1422 return EXIT_CODE_GENERIC
;
1425 used_buffer_length
= 0;
1426 while (endless_loop
) {
1430 length
= recv(sock
, data
+ used_buffer_length
, (int)(PACKET_LENGTH
- used_buffer_length
), 0);
1432 #if EWOULDBLOCK != EAGAIN
1433 || errno
== EWOULDBLOCK
1438 else if (errno
!= 0) {
1439 ws_warning("ERROR capture: %s", strerror(errno
));
1441 return EXIT_CODE_GENERIC
;
1445 ws_warning("Broken socket connection.");
1447 return EXIT_CODE_GENERIC
;
1450 used_buffer_length
+= length
;
1451 i_position
= (char *) memchr(data
, '\n', used_buffer_length
);
1452 if (i_position
&& i_position
< data
+ used_buffer_length
) {
1453 if (!strncmp(data
, "/system/bin/sh: su: not found", 29)) {
1454 ws_warning("Command 'su' not found for <%s>", adb_shell_su_hcidump
);
1456 return EXIT_CODE_GENERIC
;
1459 i_position
= (char *) memchr(i_position
+ 1, '\n', used_buffer_length
);
1462 memmove(data
, i_position
, used_buffer_length
- (i_position
- data
));
1463 used_buffer_length
= used_buffer_length
- (ssize_t
)(i_position
- data
);
1470 while (endless_loop
) {
1472 length
= recv(sock
, data
+ used_buffer_length
, (int)(PACKET_LENGTH
- used_buffer_length
), 0);
1474 #if EWOULDBLOCK != EAGAIN
1475 || errno
== EWOULDBLOCK
1480 else if (errno
!= 0) {
1481 ws_warning("ERROR capture: %s", strerror(errno
));
1483 return EXIT_CODE_GENERIC
;
1487 ws_warning("Broken socket connection.");
1489 return EXIT_CODE_GENERIC
;
1492 while (endless_loop
) {
1493 if (used_buffer_length
+ length
>= 1) {
1494 hex_data
= data
+ 29;
1495 hex
= g_ascii_strtoll(hex_data
, &new_hex_data
, 16);
1497 if ((hex
== 0x01 && used_buffer_length
+ length
>= 4) ||
1498 (hex
== 0x02 && used_buffer_length
+ length
>= 5) ||
1499 (hex
== 0x04 && used_buffer_length
+ length
>= 3)) {
1502 hex_data
= new_hex_data
;
1503 hex
= g_ascii_strtoll(hex_data
, &new_hex_data
, 16);
1504 if (hex
< 0 || hex
>= 256 || hex_data
== new_hex_data
) {
1505 ws_warning("data format %s", strerror(errno
));
1507 return EXIT_CODE_GENERIC
;
1510 hex_data
= new_hex_data
;
1511 hex
= g_ascii_strtoll(hex_data
, &new_hex_data
, 16);
1512 if (hex
< 0 || hex
>= 256 || hex_data
== new_hex_data
) {
1513 ws_warning("data format %s", strerror(errno
));
1515 return EXIT_CODE_GENERIC
;
1518 hex_data
= new_hex_data
;
1519 hex
= g_ascii_strtoll(hex_data
, &new_hex_data
, 16);
1521 raw_length
= hex
+ 4;
1522 } else if (hex
== 0x04) {
1523 hex_data
= new_hex_data
;
1524 hex
= g_ascii_strtoll(hex_data
, &new_hex_data
, 16);
1525 if (hex
< 0 || hex
>= 256 || hex_data
== new_hex_data
) {
1526 ws_warning("data format %s", strerror(errno
));
1528 return EXIT_CODE_GENERIC
;
1531 hex_data
= new_hex_data
;
1532 hex
= g_ascii_strtoll(hex_data
, &new_hex_data
, 16);
1534 raw_length
= hex
+ 3;
1535 } else if (hex
== 0x02) {
1536 hex_data
= new_hex_data
;
1537 hex
= g_ascii_strtoll(hex_data
, &new_hex_data
, 16);
1538 if (hex
< 0 || hex
>= 256 || hex_data
== new_hex_data
) {
1539 ws_warning("data format %s", strerror(errno
));
1541 return EXIT_CODE_GENERIC
;
1544 hex_data
= new_hex_data
;
1545 hex
= g_ascii_strtoll(hex_data
, &new_hex_data
, 16);
1546 if (hex
< 0 || hex
>= 256 || hex_data
== new_hex_data
) {
1547 ws_warning("data format %s", strerror(errno
));
1549 return EXIT_CODE_GENERIC
;
1552 hex_data
= new_hex_data
;
1553 hex
= g_ascii_strtoll(hex_data
, &new_hex_data
, 16);
1554 raw_length
= hex
+ 5;
1556 hex_data
= new_hex_data
;
1557 hex
= g_ascii_strtoll(hex_data
, &new_hex_data
, 16);
1558 raw_length
+= hex
<< 8;
1562 ws_warning("bad raw stream");
1564 return EXIT_CODE_GENERIC
;
1567 used_buffer_length
+= length
;
1571 frame_length
= raw_length
* 3 + (raw_length
/ 20) * 4 + ((raw_length
% 20) ? 2 : -2) + 29;
1573 if ((used_buffer_length
+ length
) < frame_length
) {
1574 used_buffer_length
+= length
;
1578 if (8 == sscanf(data
, "%04d-%02d-%02d %02d:%02d:%02d.%06d %c",
1579 &date
.tm_year
, &date
.tm_mon
, &date
.tm_mday
, &date
.tm_hour
,
1580 &date
.tm_min
, &date
.tm_sec
, &ms
, &direction_character
)) {
1582 ws_debug("time %04d-%02d-%02d %02d:%02d:%02d.%06d %c",
1583 date
.tm_year
, date
.tm_mon
, date
.tm_mday
, date
.tm_hour
,
1584 date
.tm_min
, date
.tm_sec
, ms
, direction_character
);
1586 date
.tm_year
-= 1900;
1590 new_hex_data
= data
+ 29;
1593 captured_length
= 0;
1595 while ((long)(new_hex_data
- data
+ sizeof(own_pcap_bluetooth_h4_header
)) < frame_length
) {
1596 hex_data
= new_hex_data
;
1597 hex
= g_ascii_strtoll(hex_data
, &new_hex_data
, 16);
1599 packet
[sizeof(own_pcap_bluetooth_h4_header
) + captured_length
] = (char) hex
;
1600 captured_length
+= 1;
1603 h4_header
->direction
= GINT32_TO_BE(direction_character
== '>');
1605 endless_loop
= extcap_dumper_dump(extcap_dumper
, fifo
, packet
,
1606 captured_length
+ sizeof(own_pcap_bluetooth_h4_header
),
1607 captured_length
+ sizeof(own_pcap_bluetooth_h4_header
),
1611 memmove(data
, data
+ frame_length
, (size_t)(used_buffer_length
+ length
- frame_length
));
1612 used_buffer_length
= (ssize_t
)(used_buffer_length
+ length
- frame_length
);
1618 return EXIT_CODE_SUCCESS
;
1621 /*----------------------------------------------------------------------------*/
1622 /* Android Bluetooth External Parser */
1623 /*----------------------------------------------------------------------------*/
1625 #define BLUEDROID_H4_PACKET_TYPE 0
1626 #define BLUEDROID_TIMESTAMP_SIZE 8
1627 #define BLUEDROID_H4_SIZE 1
1629 static const uint64_t BLUEDROID_TIMESTAMP_BASE
= UINT64_C(0x00dcddb30f2f8000);
1631 #define BLUEDROID_H4_PACKET_TYPE_HCI_CMD 0x01
1632 #define BLUEDROID_H4_PACKET_TYPE_ACL 0x02
1633 #define BLUEDROID_H4_PACKET_TYPE_SCO 0x03
1634 #define BLUEDROID_H4_PACKET_TYPE_HCI_EVT 0x04
1636 #define BLUEDROID_DIRECTION_SENT 0
1637 #define BLUEDROID_DIRECTION_RECV 1
1639 static int adb_forward(char *serial_number
, const char *adb_server_ip
, unsigned short *adb_server_tcp_port
,
1640 unsigned short local_tcp_port
, unsigned short server_tcp_port
) {
1641 socket_handle_t sock
;
1643 static char helpful_packet
[PACKET_LENGTH
];
1644 static const char *adb_forward_template
= "%s%s:forward:tcp:%05u;tcp:%05u";
1646 sock
= adb_connect(adb_server_ip
, adb_server_tcp_port
);
1647 if (sock
== INVALID_SOCKET
)
1648 return EXIT_CODE_INVALID_SOCKET_5
;
1650 result
= snprintf(helpful_packet
, PACKET_LENGTH
, adb_forward_template
, (serial_number
) ? "host-serial:" : "host", (serial_number
) ? serial_number
: "", local_tcp_port
, server_tcp_port
);
1651 if (result
<= 0 || result
> PACKET_LENGTH
) {
1652 ws_warning("Error while completing adb packet");
1654 return EXIT_CODE_BAD_SIZE_OF_ASSEMBLED_ADB_PACKET_12
;
1657 result
= adb_send(sock
, helpful_packet
);
1663 static int capture_android_bluetooth_external_parser(char *interface
,
1664 char *fifo
, const char *adb_server_ip
, unsigned short *adb_server_tcp_port
,
1665 unsigned short *bt_server_tcp_port
, unsigned int bt_forward_socket
, const char *bt_local_ip
,
1666 unsigned short *bt_local_tcp_port
) {
1667 struct extcap_dumper extcap_dumper
;
1668 static char buffer
[PACKET_LENGTH
];
1669 uint64_t *timestamp
;
1670 char *packet
= buffer
+ BLUEDROID_TIMESTAMP_SIZE
- sizeof(own_pcap_bluetooth_h4_header
); /* skip timestamp (8 bytes) and reuse its space for header */
1671 own_pcap_bluetooth_h4_header
*h4_header
;
1672 uint8_t *payload
= packet
+ sizeof(own_pcap_bluetooth_h4_header
);
1673 const char *adb_tcp_bluedroid_external_parser_template
= "tcp:%05u";
1676 ssize_t used_buffer_length
= 0;
1678 socket_handle_t sock
;
1679 struct sockaddr_in server
;
1680 int captured_length
;
1681 char *serial_number
;
1682 static unsigned int id
= 1;
1683 struct sockaddr_in client
;
1685 SET_DATA(timestamp
, value_u64
, buffer
);
1686 SET_DATA(h4_header
, value_own_pcap_bluetooth_h4_header
, packet
);
1688 extcap_dumper
= extcap_dumper_open(fifo
, EXTCAP_ENCAP_BLUETOOTH_H4_WITH_PHDR
);
1689 serial_number
= get_serial_from_interface(interface
);
1691 if (bt_forward_socket
) {
1692 if ((sock
= socket(AF_INET
, SOCK_STREAM
, IPPROTO_TCP
)) == INVALID_SOCKET
) {
1693 ws_warning("Cannot open system TCP socket: %s", strerror(errno
));
1694 return EXIT_CODE_GENERIC
;
1697 ws_debug("Using config: Server TCP Port=%u, Local IP=%s, Local TCP Port=%u",
1698 *bt_server_tcp_port
, bt_local_ip
, *bt_local_tcp_port
);
1700 if (*bt_local_tcp_port
!= 0) {
1703 result
= adb_forward(serial_number
, adb_server_ip
, adb_server_tcp_port
, *bt_local_tcp_port
, *bt_server_tcp_port
);
1704 ws_debug("DO: adb forward tcp:%u (local) tcp:%u (remote) result=%i",
1705 *bt_local_tcp_port
, *bt_server_tcp_port
, result
);
1708 memset(&server
, 0 , sizeof(server
));
1709 server
.sin_family
= AF_INET
;
1710 server
.sin_port
= GINT16_TO_BE(*bt_local_tcp_port
);
1711 ws_inet_pton4(bt_local_ip
, (ws_in4_addr
*)&(server
.sin_addr
.s_addr
));
1713 useSndTimeout(sock
);
1715 if (connect(sock
, (struct sockaddr
*) &server
, sizeof(server
)) == SOCKET_ERROR
) {
1716 ws_warning("<%s> Please check that adb daemon is running.", strerror(errno
));
1718 return EXIT_CODE_GENERIC
;
1721 slen
= (socklen_t
)sizeof(client
);
1722 if (getsockname(sock
, (struct sockaddr
*) &client
, &slen
)) {
1723 ws_warning("getsockname: %s", strerror(errno
));
1725 return EXIT_CODE_GENERIC
;
1728 if (slen
!= sizeof(client
)) {
1729 ws_warning("incorrect length");
1731 return EXIT_CODE_GENERIC
;
1734 ws_debug("Client port %u", GUINT16_FROM_BE(client
.sin_port
));
1738 sock
= adb_connect_transport(adb_server_ip
, adb_server_tcp_port
, serial_number
);
1739 if (sock
== INVALID_SOCKET
)
1740 return EXIT_CODE_INVALID_SOCKET_6
;
1742 result
= snprintf((char *) buffer
, PACKET_LENGTH
, adb_tcp_bluedroid_external_parser_template
, *bt_server_tcp_port
);
1743 if (result
<= 0 || result
> PACKET_LENGTH
) {
1744 ws_warning("Error while completing adb packet");
1746 return EXIT_CODE_BAD_SIZE_OF_ASSEMBLED_ADB_PACKET_14
;
1749 result
= adb_send(sock
, buffer
);
1751 ws_warning("Error while forwarding adb port");
1753 return EXIT_CODE_GENERIC
;
1757 while (endless_loop
) {
1759 length
= recv(sock
, buffer
+ used_buffer_length
, (int)(PACKET_LENGTH
- used_buffer_length
), 0);
1761 #if EWOULDBLOCK != EAGAIN
1762 || errno
== EWOULDBLOCK
1767 else if (errno
!= 0) {
1768 ws_warning("ERROR capture: %s", strerror(errno
));
1770 return EXIT_CODE_GENERIC
;
1774 if (bt_forward_socket
) {
1775 /* NOTE: Workaround... It seems that Bluedroid is slower and we can connect to socket that are not really ready... */
1776 ws_warning("Broken socket connection. Try reconnect.");
1779 if ((sock
= socket(AF_INET
, SOCK_STREAM
, IPPROTO_TCP
)) == INVALID_SOCKET
) {
1780 ws_warning("%s", strerror(errno
));
1781 return EXIT_CODE_GENERIC
;
1784 server
.sin_family
= AF_INET
;
1785 server
.sin_port
= GINT16_TO_BE(*bt_local_tcp_port
);
1786 ws_inet_pton4(bt_local_ip
, (ws_in4_addr
*)&(server
.sin_addr
.s_addr
));
1788 useSndTimeout(sock
);
1790 if (connect(sock
, (struct sockaddr
*) &server
, sizeof(server
)) == SOCKET_ERROR
) {
1791 ws_warning("ERROR reconnect: <%s> Please check that adb daemon is running.", strerror(errno
));
1793 return EXIT_CODE_GENERIC
;
1796 ws_warning("Broken socket connection.");
1798 return EXIT_CODE_GENERIC
;
1804 used_buffer_length
+= length
;
1806 ws_debug("Received: length=%"PRIdMAX
, (intmax_t)length
);
1808 while (((payload
[BLUEDROID_H4_PACKET_TYPE
] == BLUEDROID_H4_PACKET_TYPE_HCI_CMD
|| payload
[BLUEDROID_H4_PACKET_TYPE
] == BLUEDROID_H4_PACKET_TYPE_SCO
) &&
1809 used_buffer_length
>= BLUEDROID_TIMESTAMP_SIZE
+ BLUEDROID_H4_SIZE
+ 2 + 1 &&
1810 BLUEDROID_TIMESTAMP_SIZE
+ BLUEDROID_H4_SIZE
+ 2 + payload
[BLUEDROID_H4_SIZE
+ 2] + 1 <= used_buffer_length
) ||
1811 (payload
[BLUEDROID_H4_PACKET_TYPE
] == BLUEDROID_H4_PACKET_TYPE_ACL
&&
1812 used_buffer_length
>= BLUEDROID_TIMESTAMP_SIZE
+ BLUEDROID_H4_SIZE
+ 2 + 2 &&
1813 BLUEDROID_TIMESTAMP_SIZE
+ BLUEDROID_H4_SIZE
+ 2 + payload
[BLUEDROID_H4_SIZE
+ 2] + (payload
[BLUEDROID_H4_SIZE
+ 2 + 1] << 8) + 2 <= used_buffer_length
) ||
1814 (payload
[BLUEDROID_H4_PACKET_TYPE
] == BLUEDROID_H4_PACKET_TYPE_SCO
&&
1815 used_buffer_length
>= BLUEDROID_TIMESTAMP_SIZE
+ BLUEDROID_H4_SIZE
+ 2 + 1 &&
1816 BLUEDROID_TIMESTAMP_SIZE
+ BLUEDROID_H4_SIZE
+ 2 + payload
[BLUEDROID_H4_SIZE
+ 2] + 1 <= used_buffer_length
) ||
1817 (payload
[BLUEDROID_H4_PACKET_TYPE
] == BLUEDROID_H4_PACKET_TYPE_HCI_EVT
&&
1818 used_buffer_length
>= BLUEDROID_TIMESTAMP_SIZE
+ BLUEDROID_H4_SIZE
+ 1 + 1 &&
1819 BLUEDROID_TIMESTAMP_SIZE
+ BLUEDROID_H4_SIZE
+ 1 + payload
[BLUEDROID_H4_SIZE
+ 1] + 1 <= used_buffer_length
)) {
1821 ts
= GINT64_FROM_BE(*timestamp
);
1823 switch (payload
[BLUEDROID_H4_PACKET_TYPE
]) {
1824 case BLUEDROID_H4_PACKET_TYPE_HCI_CMD
:
1825 h4_header
->direction
= GINT32_TO_BE(BLUEDROID_DIRECTION_SENT
);
1827 captured_length
= (unsigned int)sizeof(own_pcap_bluetooth_h4_header
) + payload
[3] + 4;
1829 length
= sizeof(own_pcap_bluetooth_h4_header
) + BLUEDROID_H4_SIZE
+ 2 + 1 + payload
[3];
1832 case BLUEDROID_H4_PACKET_TYPE_ACL
:
1833 h4_header
->direction
= (payload
[2] & 0x80) ? GINT32_TO_BE(BLUEDROID_DIRECTION_RECV
) : GINT32_TO_BE(BLUEDROID_DIRECTION_SENT
);
1835 captured_length
= (unsigned int)sizeof(own_pcap_bluetooth_h4_header
) + payload
[3] + (payload
[3 + 1] << 8) + 5;
1837 length
= sizeof(own_pcap_bluetooth_h4_header
) + BLUEDROID_H4_SIZE
+ 2 + 2 + payload
[3] + (ssize_t
)(payload
[3 + 1] << 8);
1840 case BLUEDROID_H4_PACKET_TYPE_SCO
:
1841 h4_header
->direction
= (payload
[2] & 0x80) ? GINT32_TO_BE(BLUEDROID_DIRECTION_RECV
) : GINT32_TO_BE(BLUEDROID_DIRECTION_SENT
);
1843 captured_length
= (unsigned int)sizeof(own_pcap_bluetooth_h4_header
) + payload
[3] + 4;
1845 length
= sizeof(own_pcap_bluetooth_h4_header
) + BLUEDROID_H4_SIZE
+ 2 + 1 + payload
[3];
1848 case BLUEDROID_H4_PACKET_TYPE_HCI_EVT
:
1849 h4_header
->direction
= GINT32_TO_BE(BLUEDROID_DIRECTION_RECV
);
1851 captured_length
= (unsigned int)sizeof(own_pcap_bluetooth_h4_header
) + payload
[2] + 3;
1853 length
= sizeof(own_pcap_bluetooth_h4_header
) + BLUEDROID_H4_SIZE
+ 1 + 1 + payload
[2];
1857 ws_warning("Invalid stream");
1859 return EXIT_CODE_GENERIC
;
1862 ws_debug("\t Packet %u: used_buffer_length=%"PRIdMAX
" length=%"PRIdMAX
" captured_length=%i type=0x%02x", id
, (intmax_t)used_buffer_length
, (intmax_t)length
, captured_length
, payload
[BLUEDROID_H4_PACKET_TYPE
]);
1863 if (payload
[BLUEDROID_H4_PACKET_TYPE
] == BLUEDROID_H4_PACKET_TYPE_HCI_EVT
)
1864 ws_debug("\t Packet: %02x %02x %02x", (unsigned int) payload
[0], (unsigned int) payload
[1], (unsigned int)payload
[2]);
1867 ts
-= BLUEDROID_TIMESTAMP_BASE
;
1869 endless_loop
= extcap_dumper_dump(extcap_dumper
, fifo
, packet
,
1872 (uint32_t)(ts
/ 1000000),
1873 ((uint32_t)(ts
% 1000000)) * 1000);
1875 used_buffer_length
-= length
- sizeof(own_pcap_bluetooth_h4_header
) + BLUEDROID_TIMESTAMP_SIZE
;
1876 if (used_buffer_length
< 0) {
1877 ws_warning("Internal Negative used buffer length.");
1879 return EXIT_CODE_GENERIC
;
1881 memmove(buffer
, packet
+ length
, used_buffer_length
);
1886 return EXIT_CODE_SUCCESS
;
1889 /*----------------------------------------------------------------------------*/
1890 /* Android Btsnoop Net */
1891 /*----------------------------------------------------------------------------*/
1893 static int capture_android_bluetooth_btsnoop_net(char *interface
, char *fifo
,
1894 const char *adb_server_ip
, unsigned short *adb_server_tcp_port
) {
1895 struct extcap_dumper extcap_dumper
;
1896 static char packet
[PACKET_LENGTH
];
1898 ssize_t used_buffer_length
= 0;
1899 socket_handle_t sock
;
1900 const char *adb_tcp_btsnoop_net
= "tcp:8872";
1902 char *serial_number
;
1904 static const uint64_t BTSNOOP_TIMESTAMP_BASE
= UINT64_C(0x00dcddb30f2f8000);
1905 uint32_t *reported_length
;
1906 uint32_t *captured_length
;
1908 /* uint32_t *cumulative_dropped_packets; */
1909 uint64_t *timestamp
;
1910 char *payload
= packet
+ sizeof(own_pcap_bluetooth_h4_header
) + 24;
1911 own_pcap_bluetooth_h4_header
*h4_header
;
1913 SET_DATA(reported_length
, value_u32
, packet
+ sizeof(own_pcap_bluetooth_h4_header
) + 0);
1914 SET_DATA(captured_length
, value_u32
, packet
+ sizeof(own_pcap_bluetooth_h4_header
) + 4);
1915 SET_DATA(flags
, value_u32
, packet
+ sizeof(own_pcap_bluetooth_h4_header
) + 8);
1916 /* SET_DATA(cumulative_dropped_packets, value_u32, packet + sizeof(own_pcap_bluetooth_h4_header) + 12); */
1917 SET_DATA(timestamp
, value_u64
, packet
+ sizeof(own_pcap_bluetooth_h4_header
) + 16);
1918 SET_DATA(h4_header
, value_own_pcap_bluetooth_h4_header
, payload
- sizeof(own_pcap_bluetooth_h4_header
));
1920 extcap_dumper
= extcap_dumper_open(fifo
, EXTCAP_ENCAP_BLUETOOTH_H4_WITH_PHDR
);
1921 serial_number
= get_serial_from_interface(interface
);
1922 sock
= adb_connect_transport(adb_server_ip
, adb_server_tcp_port
, serial_number
);
1923 if (sock
== INVALID_SOCKET
)
1924 return EXIT_CODE_INVALID_SOCKET_7
;
1926 result
= adb_send(sock
, adb_tcp_btsnoop_net
);
1928 ws_warning("Error while sending command <%s>", adb_tcp_btsnoop_net
);
1930 return EXIT_CODE_ERROR_WHILE_SENDING_ADB_PACKET_2
;
1933 /* Read "btsnoop" header - 16 bytes */
1934 while (used_buffer_length
< BTSNOOP_HDR_LEN
) {
1935 length
= recv(sock
, packet
+ used_buffer_length
, (int)(BTSNOOP_HDR_LEN
- used_buffer_length
), 0);
1937 ws_warning("Broken socket connection.");
1939 return EXIT_CODE_GENERIC
;
1941 used_buffer_length
+= length
;
1943 used_buffer_length
= 0;
1945 while (endless_loop
) {
1947 length
= recv(sock
, packet
+ used_buffer_length
+ sizeof(own_pcap_bluetooth_h4_header
),
1948 (int)(PACKET_LENGTH
- sizeof(own_pcap_bluetooth_h4_header
) - used_buffer_length
), 0);
1950 #if EWOULDBLOCK != EAGAIN
1951 || errno
== EWOULDBLOCK
1956 else if (errno
!= 0) {
1957 ws_warning("ERROR capture: %s", strerror(errno
));
1959 return EXIT_CODE_GENERIC
;
1963 ws_warning("Broken socket connection.");
1965 return EXIT_CODE_GENERIC
;
1968 used_buffer_length
+= length
;
1970 while (used_buffer_length
>= 24 &&
1971 used_buffer_length
>= (int) (24 + GINT32_FROM_BE(*captured_length
))) {
1974 ts
= GINT64_FROM_BE(*timestamp
);
1975 ts
-= BTSNOOP_TIMESTAMP_BASE
;
1977 direction
= GINT32_FROM_BE(*flags
) & 0x01;
1978 h4_header
->direction
= GINT32_TO_BE(direction
);
1980 endless_loop
= extcap_dumper_dump(extcap_dumper
, fifo
,
1981 payload
- sizeof(own_pcap_bluetooth_h4_header
),
1982 GINT32_FROM_BE(*captured_length
) + sizeof(own_pcap_bluetooth_h4_header
),
1983 GINT32_FROM_BE(*reported_length
) + sizeof(own_pcap_bluetooth_h4_header
),
1984 (uint32_t)(ts
/ 1000000),
1985 ((uint32_t)(ts
% 1000000)) * 1000);
1987 used_buffer_length
-= 24 + GINT32_FROM_BE(*captured_length
);
1988 if (used_buffer_length
< 0) {
1989 ws_warning("Internal Negative used buffer length.");
1991 return EXIT_CODE_GENERIC
;
1994 if (used_buffer_length
> 0)
1995 memmove(packet
+ sizeof(own_pcap_bluetooth_h4_header
), payload
+ GINT32_FROM_BE(*captured_length
), used_buffer_length
);
2000 return EXIT_CODE_SUCCESS
;
2003 /*----------------------------------------------------------------------------*/
2004 /* Android Logcat Text*/
2005 /*----------------------------------------------------------------------------*/
2008 static int capture_android_logcat_text(char *interface
, char *fifo
,
2009 const char *adb_server_ip
, unsigned short *adb_server_tcp_port
,
2010 int logcat_ignore_log_buffer
, const char *logcat_custom_parameter
) {
2011 struct extcap_dumper extcap_dumper
;
2012 static char packet
[PACKET_LENGTH
];
2014 size_t used_buffer_length
= 0;
2015 socket_handle_t sock
;
2016 const char *protocol_name
;
2017 size_t exported_pdu_headers_size
= 0;
2018 struct exported_pdu_header exported_pdu_header_protocol_normal
;
2019 struct exported_pdu_header
*exported_pdu_header_protocol
;
2020 struct exported_pdu_header exported_pdu_header_end
= {0, 0};
2021 static const char *wireshark_protocol_logcat_text
= "logcat_text_threadtime";
2022 const char *adb_logcat_template
= "shell:export ANDROID_LOG_TAGS=\"\" ; exec logcat -v threadtime%s%s %s";
2023 char *serial_number
= NULL
;
2026 const char *logcat_buffer
;
2027 const char *logcat_log_buffer
;
2029 extcap_dumper
= extcap_dumper_open(fifo
, EXTCAP_ENCAP_WIRESHARK_UPPER_PDU
);
2031 exported_pdu_header_protocol_normal
.tag
= GUINT16_TO_BE(EXP_PDU_TAG_DISSECTOR_NAME
);
2032 exported_pdu_header_protocol_normal
.length
= GUINT16_TO_BE(strlen(wireshark_protocol_logcat_text
) + 2);
2034 serial_number
= get_serial_from_interface(interface
);
2035 sock
= adb_connect_transport(adb_server_ip
, adb_server_tcp_port
, serial_number
);
2036 if (sock
== INVALID_SOCKET
)
2037 return EXIT_CODE_INVALID_SOCKET_8
;
2039 if (is_specified_interface(interface
, INTERFACE_ANDROID_LOGCAT_MAIN
) || is_specified_interface(interface
, INTERFACE_ANDROID_LOGCAT_TEXT_MAIN
))
2040 logcat_buffer
= " -b main";
2041 else if (is_specified_interface(interface
, INTERFACE_ANDROID_LOGCAT_SYSTEM
) || is_specified_interface(interface
, INTERFACE_ANDROID_LOGCAT_TEXT_SYSTEM
))
2042 logcat_buffer
= " -b system";
2043 else if (is_specified_interface(interface
, INTERFACE_ANDROID_LOGCAT_RADIO
) || is_specified_interface(interface
, INTERFACE_ANDROID_LOGCAT_TEXT_RADIO
))
2044 logcat_buffer
= " -b radio";
2045 else if (is_specified_interface(interface
, INTERFACE_ANDROID_LOGCAT_EVENTS
) || is_specified_interface(interface
, INTERFACE_ANDROID_LOGCAT_TEXT_EVENTS
))
2046 logcat_buffer
= " -b events";
2047 else if (is_specified_interface(interface
, INTERFACE_ANDROID_LOGCAT_TEXT_CRASH
))
2048 logcat_buffer
= " -b crash";
2050 ws_warning("Unknown interface: <%s>", interface
);
2052 return EXIT_CODE_GENERIC
;
2055 if (logcat_ignore_log_buffer
)
2056 logcat_log_buffer
= " -T 1";
2058 logcat_log_buffer
= "";
2060 if (!logcat_custom_parameter
)
2061 logcat_custom_parameter
= "";
2063 result
= snprintf((char *) packet
, PACKET_LENGTH
, adb_logcat_template
, logcat_buffer
, logcat_log_buffer
, logcat_custom_parameter
);
2064 if (result
<= 0 || result
> PACKET_LENGTH
) {
2065 ws_warning("Error while completing adb packet");
2067 return EXIT_CODE_BAD_SIZE_OF_ASSEMBLED_ADB_PACKET_17
;
2070 result
= adb_send(sock
, packet
);
2072 ws_warning("Error while sending command <%s>", packet
);
2074 return EXIT_CODE_ERROR_WHILE_SENDING_ADB_PACKET_3
;
2077 protocol_name
= wireshark_protocol_logcat_text
;
2078 exported_pdu_header_protocol
= &exported_pdu_header_protocol_normal
;
2080 memcpy(packet
, exported_pdu_header_protocol
, sizeof(struct exported_pdu_header
));
2081 exported_pdu_headers_size
+= sizeof(struct exported_pdu_header
);
2083 memcpy(packet
+ exported_pdu_headers_size
, protocol_name
, GUINT16_FROM_BE(exported_pdu_header_protocol
->length
) - 2);
2084 exported_pdu_headers_size
+= GUINT16_FROM_BE(exported_pdu_header_protocol
->length
);
2086 packet
[exported_pdu_headers_size
- 1] = 0;
2087 packet
[exported_pdu_headers_size
- 2] = 0;
2089 memcpy(packet
+ exported_pdu_headers_size
, &exported_pdu_header_end
, sizeof(struct exported_pdu_header
));
2090 exported_pdu_headers_size
+= sizeof(struct exported_pdu_header
) + GUINT16_FROM_BE(exported_pdu_header_end
.length
);
2092 used_buffer_length
= 0;
2093 while (endless_loop
) {
2095 length
= recv(sock
, packet
+ exported_pdu_headers_size
+ used_buffer_length
, (int)(PACKET_LENGTH
- exported_pdu_headers_size
- used_buffer_length
), 0);
2097 #if EWOULDBLOCK != EAGAIN
2098 || errno
== EWOULDBLOCK
2103 else if (errno
!= 0) {
2104 ws_warning("ERROR capture: %s", strerror(errno
));
2106 return EXIT_CODE_GENERIC
;
2110 ws_warning("Broken socket connection. Try reconnect.");
2112 return EXIT_CODE_GENERIC
;
2115 used_buffer_length
+= length
;
2117 while (used_buffer_length
> 0 && (pos
= (char *) memchr(packet
+ exported_pdu_headers_size
, '\n', used_buffer_length
))) {
2125 length
= (ssize_t
)(pos
- packet
) + 1;
2128 date
= localtime(&t
);
2131 if (6 == sscanf(packet
+ exported_pdu_headers_size
, "%d-%d %d:%d:%d.%d", &date
->tm_mon
, &date
->tm_mday
, &date
->tm_hour
,
2132 &date
->tm_min
, &date
->tm_sec
, &ms
)) {
2134 date
->tm_isdst
= -1;
2135 seconds
= mktime(date
);
2136 secs
= (time_t) seconds
;
2137 nsecs
= (int) (ms
* 1e6
);
2140 endless_loop
= extcap_dumper_dump(extcap_dumper
, fifo
, packet
,
2145 memmove(packet
+ exported_pdu_headers_size
, packet
+ length
, used_buffer_length
+ exported_pdu_headers_size
- length
);
2146 used_buffer_length
-= length
- exported_pdu_headers_size
;
2151 return EXIT_CODE_SUCCESS
;
2154 /*----------------------------------------------------------------------------*/
2155 /* Android Logger / Logcat */
2156 /*----------------------------------------------------------------------------*/
2158 static int capture_android_logcat(char *interface
, char *fifo
,
2159 const char *adb_server_ip
, unsigned short *adb_server_tcp_port
) {
2160 struct extcap_dumper extcap_dumper
;
2161 static char packet
[PACKET_LENGTH
];
2163 size_t used_buffer_length
= 0;
2164 socket_handle_t sock
;
2165 const char *protocol_name
;
2166 size_t exported_pdu_headers_size
= 0;
2167 struct exported_pdu_header exported_pdu_header_protocol_events
;
2168 struct exported_pdu_header exported_pdu_header_protocol_normal
;
2169 struct exported_pdu_header
*exported_pdu_header_protocol
;
2170 struct exported_pdu_header exported_pdu_header_end
= {0, 0};
2171 static const char *wireshark_protocol_logcat
= "logcat";
2172 static const char *wireshark_protocol_logcat_events
= "logcat_events";
2173 const char *adb_command
;
2174 uint16_t *payload_length
;
2175 uint16_t *try_header_size
;
2176 uint32_t *timestamp_secs
;
2177 uint32_t *timestamp_nsecs
;
2178 uint16_t header_size
;
2180 char *serial_number
= NULL
;
2182 extcap_dumper
= extcap_dumper_open(fifo
, EXTCAP_ENCAP_WIRESHARK_UPPER_PDU
);
2184 exported_pdu_header_protocol_events
.tag
= GUINT16_TO_BE(EXP_PDU_TAG_DISSECTOR_NAME
);
2185 exported_pdu_header_protocol_events
.length
= GUINT16_TO_BE(strlen(wireshark_protocol_logcat_events
) + 2);
2187 exported_pdu_header_protocol_normal
.tag
= GUINT16_TO_BE(EXP_PDU_TAG_DISSECTOR_NAME
);
2188 exported_pdu_header_protocol_normal
.length
= GUINT16_TO_BE(strlen(wireshark_protocol_logcat
) + 2);
2190 serial_number
= get_serial_from_interface(interface
);
2191 sock
= adb_connect_transport(adb_server_ip
, adb_server_tcp_port
, serial_number
);
2192 if (sock
== INVALID_SOCKET
)
2193 return EXIT_CODE_INVALID_SOCKET_9
;
2195 adb_command
= interface_to_logbuf(interface
);
2197 ws_warning("Unknown interface: <%s>", interface
);
2199 return EXIT_CODE_GENERIC
;
2202 result
= adb_send(sock
, adb_command
);
2204 ws_warning("Error while sending command <%s>", adb_command
);
2206 return EXIT_CODE_ERROR_WHILE_SENDING_ADB_PACKET_4
;
2209 if (is_specified_interface(interface
, INTERFACE_ANDROID_LOGCAT_EVENTS
))
2211 protocol_name
= wireshark_protocol_logcat_events
;
2212 exported_pdu_header_protocol
= &exported_pdu_header_protocol_events
;
2214 protocol_name
= wireshark_protocol_logcat
;
2215 exported_pdu_header_protocol
= &exported_pdu_header_protocol_normal
;
2218 memcpy(packet
, exported_pdu_header_protocol
, sizeof(struct exported_pdu_header
));
2219 exported_pdu_headers_size
+= sizeof(struct exported_pdu_header
);
2221 memcpy(packet
+ exported_pdu_headers_size
, protocol_name
, GUINT16_FROM_BE(exported_pdu_header_protocol
->length
) - 2);
2222 exported_pdu_headers_size
+= GUINT16_FROM_BE(exported_pdu_header_protocol
->length
);
2224 packet
[exported_pdu_headers_size
- 1] = 0;
2225 packet
[exported_pdu_headers_size
- 2] = 0;
2227 memcpy(packet
+ exported_pdu_headers_size
, &exported_pdu_header_end
, sizeof(struct exported_pdu_header
));
2228 exported_pdu_headers_size
+= sizeof(struct exported_pdu_header
) + GUINT16_FROM_BE(exported_pdu_header_end
.length
);
2230 SET_DATA(payload_length
, value_u16
, packet
+ exported_pdu_headers_size
+ 0);
2231 SET_DATA(try_header_size
, value_u16
, packet
+ exported_pdu_headers_size
+ 2);
2232 SET_DATA(timestamp_secs
, value_u32
, packet
+ exported_pdu_headers_size
+ 12);
2233 SET_DATA(timestamp_nsecs
, value_u32
, packet
+ exported_pdu_headers_size
+ 16);
2235 while (endless_loop
) {
2237 length
= recv(sock
, packet
+ exported_pdu_headers_size
+ used_buffer_length
, (int)(PACKET_LENGTH
- exported_pdu_headers_size
- used_buffer_length
), 0);
2239 #if EWOULDBLOCK != EAGAIN
2240 || errno
== EWOULDBLOCK
2245 else if (errno
!= 0) {
2246 ws_warning("ERROR capture: %s", strerror(errno
));
2248 return EXIT_CODE_GENERIC
;
2252 while (endless_loop
) {
2253 ws_warning("Broken socket connection. Try reconnect.");
2254 used_buffer_length
= 0;
2257 sock
= adb_connect_transport(adb_server_ip
, adb_server_tcp_port
, serial_number
);
2258 if (sock
== INVALID_SOCKET
)
2259 return EXIT_CODE_INVALID_SOCKET_10
;
2261 result
= adb_send(sock
, adb_command
);
2263 ws_warning("WARNING: Error while sending command <%s>", adb_command
);
2271 used_buffer_length
+= length
+ exported_pdu_headers_size
;
2273 if (*try_header_size
!= 24)
2276 header_size
= *try_header_size
;
2278 length
= (*payload_length
) + header_size
+ (ssize_t
)exported_pdu_headers_size
;
2280 while (used_buffer_length
>= exported_pdu_headers_size
+ header_size
&& (size_t)length
<= used_buffer_length
) {
2281 endless_loop
= extcap_dumper_dump(extcap_dumper
, fifo
, packet
,
2284 *timestamp_secs
, *timestamp_nsecs
);
2286 memmove(packet
+ exported_pdu_headers_size
, packet
+ length
, used_buffer_length
- length
);
2287 used_buffer_length
-= length
;
2288 used_buffer_length
+= exported_pdu_headers_size
;
2291 length
= (*payload_length
) + header_size
+ (ssize_t
)exported_pdu_headers_size
;
2293 if (*try_header_size
!= 24)
2296 header_size
= *try_header_size
;
2298 used_buffer_length
-= exported_pdu_headers_size
;
2303 return EXIT_CODE_SUCCESS
;
2307 /*----------------------------------------------------------------------------*/
2308 /* Android Wifi Tcpdump */
2309 /* The Tcpdump sends data in pcap format. So for using the extcap_dumper we */
2310 /* need to unpack the pcap and then send the packet data to the dumper. */
2311 /*----------------------------------------------------------------------------*/
2312 static int capture_android_tcpdump(char *interface
, char *fifo
,
2313 char *capture_filter
, const char *adb_server_ip
,
2314 unsigned short *adb_server_tcp_port
) {
2315 static const char *const adb_shell_tcpdump_format
= "exec:tcpdump -U -n -s 0 -u -i %s -w - %s 2>/dev/null";
2316 static const char *const regex_interface
= INTERFACE_ANDROID_TCPDUMP
"-(?<iface>.*?)-(?<serial>.*)";
2317 struct extcap_dumper extcap_dumper
;
2318 static char data
[PACKET_LENGTH
];
2320 ssize_t used_buffer_length
= 0;
2321 ssize_t frame_length
=0;
2322 socket_handle_t sock
;
2325 char *serial_number
= NULL
;
2326 bool nanosecond_timestamps
;
2327 bool swap_byte_order
;
2328 pcap_hdr_t
*global_header
;
2329 pcaprec_hdr_t p_header
;
2330 GRegex
*regex
= NULL
;
2332 GMatchInfo
*match
= NULL
;
2333 char *tcpdump_cmd
= NULL
;
2334 char *quoted_filter
= NULL
;
2336 regex
= g_regex_new(regex_interface
, G_REGEX_RAW
, (GRegexMatchFlags
)0, &err
);
2338 ws_warning("Failed to compile regex for tcpdump interface");
2339 return EXIT_CODE_GENERIC
;
2342 g_regex_match(regex
, interface
, (GRegexMatchFlags
)0, &match
);
2343 if (!g_match_info_matches(match
)) {
2344 ws_warning("Failed to determine iface name and serial number");
2345 g_regex_unref(regex
);
2346 return EXIT_CODE_GENERIC
;
2349 iface
= g_match_info_fetch_named(match
, "iface");
2350 serial_number
= g_match_info_fetch_named(match
, "serial");
2351 g_match_info_free(match
);
2352 g_regex_unref(regex
);
2354 /* First check for the device if it is connected or not */
2355 sock
= adb_connect_transport(adb_server_ip
, adb_server_tcp_port
, serial_number
);
2356 g_free(serial_number
);
2357 if (sock
== INVALID_SOCKET
) {
2359 return EXIT_CODE_INVALID_SOCKET_11
;
2362 quoted_filter
= g_shell_quote(capture_filter
? capture_filter
: "");
2363 tcpdump_cmd
= ws_strdup_printf(adb_shell_tcpdump_format
, iface
, quoted_filter
);
2365 g_free(quoted_filter
);
2366 result
= adb_send(sock
, tcpdump_cmd
);
2367 g_free(tcpdump_cmd
);
2369 ws_warning("Error while setting adb transport");
2371 return EXIT_CODE_GENERIC
;
2374 while (used_buffer_length
< PCAP_GLOBAL_HEADER_LENGTH
) {
2376 length
= recv(sock
, data
+ used_buffer_length
, (int)(PCAP_GLOBAL_HEADER_LENGTH
- used_buffer_length
), 0);
2378 #if EWOULDBLOCK != EAGAIN
2379 || errno
== EWOULDBLOCK
2384 else if (errno
!= 0) {
2385 ws_warning("ERROR capture: %s", strerror(errno
));
2387 return EXIT_CODE_GENERIC
;
2391 ws_warning("Broken socket connection.");
2393 return EXIT_CODE_GENERIC
;
2396 used_buffer_length
+= length
;
2399 global_header
= (pcap_hdr_t
*) data
;
2400 switch (global_header
->magic_number
) {
2402 swap_byte_order
= false;
2403 nanosecond_timestamps
= false;
2406 swap_byte_order
= true;
2407 nanosecond_timestamps
= false;
2410 swap_byte_order
= false;
2411 nanosecond_timestamps
= true;
2414 swap_byte_order
= true;
2415 nanosecond_timestamps
= true;
2418 ws_warning("Received incorrect magic");
2420 return EXIT_CODE_GENERIC
;
2422 int encap
= (int)(swap_byte_order
? GUINT32_SWAP_LE_BE(global_header
->network
) : global_header
->network
);
2423 #ifndef ANDROIDDUMP_USE_LIBPCAP
2424 encap
= wtap_pcap_encap_to_wtap_encap(encap
);
2426 extcap_dumper
= extcap_dumper_open(fifo
, encap
);
2428 used_buffer_length
= 0;
2429 while (endless_loop
) {
2433 length
= recv(sock
, data
+ used_buffer_length
, (int)(PACKET_LENGTH
- used_buffer_length
), 0);
2435 #if EWOULDBLOCK != EAGAIN
2436 || errno
== EWOULDBLOCK
2441 else if (errno
!= 0) {
2442 ws_warning("ERROR capture: %s", strerror(errno
));
2444 return EXIT_CODE_GENERIC
;
2448 ws_warning("Broken socket connection.");
2450 return EXIT_CODE_GENERIC
;
2453 used_buffer_length
+= length
;
2455 while ((used_buffer_length
- offset
) > PCAP_RECORD_HEADER_LENGTH
) {
2456 p_header
= *((pcaprec_hdr_t
*) (data
+ offset
));
2457 if (swap_byte_order
) {
2458 p_header
.ts_sec
= GUINT32_SWAP_LE_BE(p_header
.ts_sec
);
2459 p_header
.ts_usec
= GUINT32_SWAP_LE_BE(p_header
.ts_usec
);
2460 p_header
.incl_len
= GUINT32_SWAP_LE_BE(p_header
.incl_len
);
2461 p_header
.orig_len
= GUINT32_SWAP_LE_BE(p_header
.orig_len
);
2463 if (!nanosecond_timestamps
) {
2464 p_header
.ts_usec
= p_header
.ts_usec
* 1000;
2467 frame_length
= p_header
.incl_len
+ PCAP_RECORD_HEADER_LENGTH
;
2468 if ((used_buffer_length
- offset
) < frame_length
) {
2469 break; /* wait for complete packet */
2472 /* It was observed that some times tcpdump reports the length of packet as '0' and that leads to the
2473 * ( Warn Error "Less data was read than was expected" while reading )
2474 * So to avoid this error we are checking for length of packet before passing it to dumper.
2476 if (p_header
.incl_len
> 0) {
2477 endless_loop
= extcap_dumper_dump(extcap_dumper
, fifo
, data
+ offset
+ PCAP_RECORD_HEADER_LENGTH
,
2478 p_header
.incl_len
, p_header
.orig_len
, p_header
.ts_sec
, p_header
.ts_usec
);
2481 offset
+= frame_length
;
2484 if (offset
< used_buffer_length
) {
2485 memmove(data
, data
+ offset
, used_buffer_length
- offset
);
2487 used_buffer_length
-= offset
;
2491 return EXIT_CODE_SUCCESS
;
2494 int main(int argc
, char *argv
[]) {
2496 int ret
= EXIT_CODE_GENERIC
;
2499 const char *adb_server_ip
= NULL
;
2500 unsigned short *adb_server_tcp_port
= NULL
;
2501 unsigned int logcat_text
= 0;
2502 unsigned int logcat_ignore_log_buffer
= 0;
2503 const char *logcat_custom_parameter
= NULL
;
2504 const char *default_adb_server_ip
= "127.0.0.1";
2505 unsigned short default_adb_server_tcp_port
= 5037;
2506 unsigned short local_adb_server_tcp_port
;
2507 unsigned short local_bt_server_tcp_port
;
2508 unsigned short local_bt_local_tcp_port
;
2509 unsigned short *bt_server_tcp_port
= NULL
;
2510 unsigned int bt_forward_socket
= 0;
2511 const char *bt_local_ip
= NULL
;
2512 unsigned short *bt_local_tcp_port
= NULL
;
2513 unsigned short default_bt_server_tcp_port
= 4330;
2514 const char *default_bt_local_ip
= "127.0.0.1";
2515 unsigned short default_bt_local_tcp_port
= 4330;
2516 extcap_parameters
* extcap_conf
= NULL
;
2518 char *help_header
= NULL
;
2520 /* Set the program name. */
2521 g_set_prgname("androiddump");
2523 cmdarg_err_init(extcap_log_cmdarg_err
, extcap_log_cmdarg_err
);
2525 /* Initialize log handler early so we can have proper logging during startup. */
2529 * Get credential information for later use.
2531 init_process_policies();
2534 * Attempt to get the pathname of the directory containing the
2537 err_msg
= configuration_init(argv
[0]);
2538 if (err_msg
!= NULL
) {
2539 ws_warning("Can't get pathname of directory containing the extcap program: %s.",
2544 init_report_failure_message("androiddump");
2546 extcap_conf
= g_new0(extcap_parameters
, 1);
2548 help_url
= data_file_url("androiddump.html");
2549 extcap_base_set_util_info(extcap_conf
, argv
[0], ANDROIDDUMP_VERSION_MAJOR
, ANDROIDDUMP_VERSION_MINOR
,
2550 ANDROIDDUMP_VERSION_RELEASE
, help_url
);
2553 help_header
= ws_strdup_printf(
2554 " %s --extcap-interfaces [--adb-server-ip=<arg>] [--adb-server-tcp-port=<arg>]\n"
2555 " %s --extcap-interface=INTERFACE --extcap-dlts\n"
2556 " %s --extcap-interface=INTERFACE --extcap-config\n"
2557 " %s --extcap-interface=INTERFACE --fifo=PATH_FILENAME --capture\n"
2558 "\nINTERFACE has the form TYPE-DEVICEID:\n"
2559 "\t""For example: "INTERFACE_ANDROID_BLUETOOTH_BTSNOOP_NET
"-W3D7N15C29005648""\n"
2561 "\tTYPE is one of:\n"
2562 "\t"INTERFACE_ANDROID_LOGCAT_MAIN
"\n"
2563 "\t"INTERFACE_ANDROID_LOGCAT_SYSTEM
"\n"
2564 "\t"INTERFACE_ANDROID_LOGCAT_RADIO
"\n"
2565 "\t"INTERFACE_ANDROID_LOGCAT_EVENTS
"\n"
2566 "\t"INTERFACE_ANDROID_LOGCAT_TEXT_MAIN
"\n"
2567 "\t"INTERFACE_ANDROID_LOGCAT_TEXT_SYSTEM
"\n"
2568 "\t"INTERFACE_ANDROID_LOGCAT_TEXT_RADIO
"\n"
2569 "\t"INTERFACE_ANDROID_LOGCAT_TEXT_EVENTS
"\n"
2570 "\t"INTERFACE_ANDROID_LOGCAT_TEXT_CRASH
"\n"
2571 "\t"INTERFACE_ANDROID_BLUETOOTH_HCIDUMP
"\n"
2572 "\t"INTERFACE_ANDROID_BLUETOOTH_EXTERNAL_PARSER
"\n"
2573 "\t"INTERFACE_ANDROID_BLUETOOTH_BTSNOOP_NET
"\n"
2574 "\t"INTERFACE_ANDROID_TCPDUMP
"\n"
2576 "\t""DEVICEID is the identifier of the device provided by Android SDK (see \"adb devices\")\n"
2577 "\t""For example: W3D7N15C29005648""\n",
2579 argv
[0], argv
[0], argv
[0], argv
[0]);
2580 extcap_help_add_header(extcap_conf
, help_header
);
2581 g_free(help_header
);
2583 extcap_help_add_option(extcap_conf
, "--help", "print this help");
2584 extcap_help_add_option(extcap_conf
, "--adb-server-ip <IP>", "the IP address of the ADB server");
2585 extcap_help_add_option(extcap_conf
, "--adb-server-tcp-port <port>", "the TCP port of the ADB server");
2586 extcap_help_add_option(extcap_conf
, "--logcat-text", "use logcat text format");
2587 extcap_help_add_option(extcap_conf
, "--logcat-ignore-log-buffer", "ignore log buffer");
2588 extcap_help_add_option(extcap_conf
, "--logcat-custom-options <text>", "use custom logcat parameters");
2589 extcap_help_add_option(extcap_conf
, "--bt-server-tcp-port <port>", "bluetooth server TCP port");
2590 extcap_help_add_option(extcap_conf
, "--bt-forward-socket <path>", "bluetooth forward socket");
2591 extcap_help_add_option(extcap_conf
, "--bt-local-ip <IP>", "the bluetooth local IP");
2592 extcap_help_add_option(extcap_conf
, "--bt-local-tcp-port <port>", "the bluetooth local TCP port");
2598 extcap_help_print(extcap_conf
);
2599 ret
= EXIT_CODE_SUCCESS
;
2603 while ((result
= ws_getopt_long(argc
, argv
, "", longopts
, &option_idx
)) != -1) {
2607 extcap_version_print(extcap_conf
);
2608 ret
= EXIT_CODE_SUCCESS
;
2611 extcap_help_print(extcap_conf
);
2612 ret
= EXIT_CODE_SUCCESS
;
2614 case OPT_CONFIG_ADB_SERVER_IP
:
2615 adb_server_ip
= ws_optarg
;
2617 case OPT_CONFIG_ADB_SERVER_TCP_PORT
:
2618 adb_server_tcp_port
= &local_adb_server_tcp_port
;
2620 ws_warning("Impossible exception. Parameter required argument, but there is no it right now.");
2623 if (!ws_strtou16(ws_optarg
, NULL
, adb_server_tcp_port
)) {
2624 ws_warning("Invalid adb server TCP port: %s", ws_optarg
);
2628 case OPT_CONFIG_LOGCAT_TEXT
:
2629 if (ws_optarg
&& !*ws_optarg
)
2632 logcat_text
= (g_ascii_strncasecmp(ws_optarg
, "true", 4) == 0);
2634 case OPT_CONFIG_LOGCAT_IGNORE_LOG_BUFFER
:
2635 if (ws_optarg
== NULL
|| (ws_optarg
&& !*ws_optarg
))
2636 logcat_ignore_log_buffer
= true;
2638 logcat_ignore_log_buffer
= (g_ascii_strncasecmp(ws_optarg
, "true", 4) == 0);
2640 case OPT_CONFIG_LOGCAT_CUSTOM_OPTIONS
:
2641 if (ws_optarg
== NULL
|| (ws_optarg
&& *ws_optarg
== '\0')) {
2642 logcat_custom_parameter
= NULL
;
2646 if (g_regex_match_simple("(^|\\s)-[bBcDfgLnpPrv]", ws_optarg
, G_REGEX_RAW
, (GRegexMatchFlags
)0)) {
2647 ws_error("Found prohibited option in logcat-custom-options");
2648 return EXIT_CODE_GENERIC
;
2651 logcat_custom_parameter
= ws_optarg
;
2654 case OPT_CONFIG_BT_SERVER_TCP_PORT
:
2655 bt_server_tcp_port
= &local_bt_server_tcp_port
;
2657 ws_warning("Impossible exception. Parameter required argument, but there is no it right now.");
2660 if (!ws_strtou16(ws_optarg
, NULL
, bt_server_tcp_port
)) {
2661 ws_warning("Invalid bluetooth server TCP port: %s", ws_optarg
);
2665 case OPT_CONFIG_BT_FORWARD_SOCKET
:
2666 bt_forward_socket
= (g_ascii_strncasecmp(ws_optarg
, "true", 4) == 0);
2668 case OPT_CONFIG_BT_LOCAL_IP
:
2669 bt_local_ip
= ws_optarg
;
2671 case OPT_CONFIG_BT_LOCAL_TCP_PORT
:
2672 bt_local_tcp_port
= &local_bt_local_tcp_port
;
2674 ws_warning("Impossible exception. Parameter required argument, but there is no it right now.");
2677 if (!ws_strtou16(ws_optarg
, NULL
, bt_local_tcp_port
)) {
2678 ws_warning("Invalid bluetooth local tcp port: %s", ws_optarg
);
2683 if (!extcap_base_parse_options(extcap_conf
, result
- EXTCAP_OPT_LIST_INTERFACES
, ws_optarg
))
2685 ws_warning("Invalid argument <%s>. Try --help.\n", argv
[ws_optind
- 1]);
2692 adb_server_ip
= default_adb_server_ip
;
2694 if (!adb_server_tcp_port
)
2695 adb_server_tcp_port
= &default_adb_server_tcp_port
;
2697 if (!bt_server_tcp_port
)
2698 bt_server_tcp_port
= &default_bt_server_tcp_port
;
2701 bt_local_ip
= default_bt_local_ip
;
2703 if (!bt_local_tcp_port
)
2704 bt_local_tcp_port
= &default_bt_local_tcp_port
;
2706 err_msg
= ws_init_sockets();
2707 if (err_msg
!= NULL
) {
2708 ws_warning("ERROR: %s", err_msg
);
2710 ws_warning("%s", please_report_bug());
2714 extcap_cmdline_debug(argv
, argc
);
2716 if (extcap_conf
->do_list_interfaces
)
2717 register_interfaces(extcap_conf
, adb_server_ip
, adb_server_tcp_port
);
2720 * extcap implementation calls androiddump --extcap-dlts for each interface.
2721 * The only way to know whether an interface exists or not is to go through the
2722 * whole process of listing all interfaces (i.e. calling register_interfaces
2723 * function). Since being a system resource heavy operation and repeated for
2724 * each interface instead register a fake interface to be returned for dlt
2725 * listing only purpose
2727 if (extcap_conf
->do_list_dlts
) {
2728 new_fake_interface_for_list_dlts(extcap_conf
, extcap_conf
->interface
);
2731 if (extcap_base_handle_interface(extcap_conf
)) {
2732 ret
= EXIT_CODE_SUCCESS
;
2736 if (extcap_conf
->show_config
) {
2737 ret
= list_config(extcap_conf
->interface
);
2741 if (extcap_conf
->capture
) {
2742 if (extcap_conf
->interface
&& is_logcat_interface(extcap_conf
->interface
))
2744 ret
= capture_android_logcat_text(extcap_conf
->interface
,
2745 extcap_conf
->fifo
, adb_server_ip
, adb_server_tcp_port
,
2746 logcat_ignore_log_buffer
, logcat_custom_parameter
);
2748 ret
= capture_android_logcat(extcap_conf
->interface
,
2749 extcap_conf
->fifo
, adb_server_ip
, adb_server_tcp_port
);
2750 else if (extcap_conf
->interface
&& is_logcat_text_interface(extcap_conf
->interface
))
2751 ret
= capture_android_logcat_text(extcap_conf
->interface
,
2752 extcap_conf
->fifo
, adb_server_ip
, adb_server_tcp_port
,
2753 logcat_ignore_log_buffer
, logcat_custom_parameter
);
2754 else if (extcap_conf
->interface
&& is_specified_interface(extcap_conf
->interface
, INTERFACE_ANDROID_BLUETOOTH_HCIDUMP
))
2755 ret
= capture_android_bluetooth_hcidump(extcap_conf
->interface
, extcap_conf
->fifo
, adb_server_ip
, adb_server_tcp_port
);
2756 else if (extcap_conf
->interface
&& is_specified_interface(extcap_conf
->interface
, INTERFACE_ANDROID_BLUETOOTH_EXTERNAL_PARSER
))
2757 ret
= capture_android_bluetooth_external_parser(extcap_conf
->interface
, extcap_conf
->fifo
, adb_server_ip
, adb_server_tcp_port
,
2758 bt_server_tcp_port
, bt_forward_socket
, bt_local_ip
, bt_local_tcp_port
);
2759 else if (extcap_conf
->interface
&& (is_specified_interface(extcap_conf
->interface
, INTERFACE_ANDROID_BLUETOOTH_BTSNOOP_NET
)))
2760 ret
= capture_android_bluetooth_btsnoop_net(extcap_conf
->interface
, extcap_conf
->fifo
, adb_server_ip
, adb_server_tcp_port
);
2761 else if (extcap_conf
->interface
&& (is_specified_interface(extcap_conf
->interface
,INTERFACE_ANDROID_TCPDUMP
)))
2762 ret
= capture_android_tcpdump(extcap_conf
->interface
, extcap_conf
->fifo
, extcap_conf
->capture_filter
, adb_server_ip
, adb_server_tcp_port
);
2767 /* no action was given, assume success */
2768 ret
= EXIT_CODE_SUCCESS
;
2771 /* clean up stuff */
2772 extcap_base_cleanup(&extcap_conf
);
2773 #ifndef ANDROIDDUMP_USE_LIBPCAP
2781 * Editor modelines - https://www.wireshark.org/tools/modelines.html
2786 * indent-tabs-mode: nil
2789 * vi: set shiftwidth=4 tabstop=8 expandtab:
2790 * :indentSize=4:tabSize=8:noTabs=true: