LATER... ei_kerberos_kdc_session_key ...
[wireshark-sm.git] / extcap / androiddump.c
bloba1dcb76bcc16116db7bd567c973971524a8759aa
1 /* androiddump.c
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
12 #include "config.h"
13 #define WS_LOG_DOMAIN "androiddump"
15 #include "extcap-base.h"
17 #include <stdio.h>
18 #include <stdint.h>
19 #include <string.h>
20 #include <errno.h>
21 #include <time.h>
22 #include <fcntl.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>
36 #endif
38 #ifdef HAVE_UNISTD_H
39 #include <unistd.h>
40 #endif
42 #ifdef HAVE_SYS_SOCKET_H
43 #include <sys/socket.h>
44 #endif
46 #ifdef HAVE_ARPA_INET_H
47 #include <arpa/inet.h>
48 #endif
50 #ifdef HAVE_SYS_TIME_H
51 #include <sys/time.h>
52 #endif
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
61 #include <pcap.h>
62 #include <pcap-bpf.h>
63 #include <pcap/bluetooth.h>
65 #ifndef DLT_BLUETOOTH_H4_WITH_PHDR
66 #define DLT_BLUETOOTH_H4_WITH_PHDR 201
67 #endif
69 #ifndef DLT_WIRESHARK_UPPER_PDU
70 #define DLT_WIRESHARK_UPPER_PDU 252
71 #endif
73 #ifndef PCAP_TSTAMP_PRECISION_MICRO
74 #define PCAP_TSTAMP_PRECISION_MICRO 0
75 #endif
77 #ifndef PCAP_TSTAMP_PRECISION_NANO
78 #define PCAP_TSTAMP_PRECISION_NANO 1
79 #endif
80 #else
81 #include "wiretap/wtap.h"
82 #include "wiretap/pcap-encap.h"
83 #endif
85 #include <cli_main.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
94 #else
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
101 #endif
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
137 enum exit_code {
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
187 enum {
188 EXTCAP_BASE_OPTIONS_ENUM,
189 OPT_HELP,
190 OPT_VERSION,
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[] = {
203 EXTCAP_BASE_OPTIONS,
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},
215 { 0, 0, 0, 0 }
218 struct interface_t {
219 const char *display_name;
220 const char *interface_name;
221 struct interface_t *next;
224 struct exported_pdu_header {
225 uint16_t tag;
226 uint16_t length;
227 /* unsigned char value[0]; */
231 typedef struct _own_pcap_bluetooth_h4_header {
232 uint32_t direction;
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 */
243 } pcap_hdr_t;
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 */
251 } pcaprec_hdr_t;
253 /* This fix compilator warning like "warning: cast from 'char *' to 'uint32_t *' (aka 'unsigned int *') increases required alignment from 1 to 4 " */
254 typedef union {
255 char *value_char;
256 uint8_t *value_u8;
257 uint16_t *value_u16;
258 uint32_t *value_u32;
259 uint64_t *value_u64;
260 int8_t *value_i8;
261 int16_t *value_i16;
262 int32_t *value_i32;
263 int64_t *value_i64;
264 own_pcap_bluetooth_h4_header *value_own_pcap_bluetooth_h4_header;
265 } data_aligned_t;
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 {
276 int encap;
277 union {
278 #ifdef ANDROIDDUMP_USE_LIBPCAP
279 pcap_dumper_t *pcap;
280 #else
281 wtap_dumper *wtap;
282 #endif
283 } dumper;
286 /* Globals */
287 static int endless_loop = 1;
289 /* Functions */
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,
324 NULL
326 int i;
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;
334 return NULL;
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;
353 return logbuf;
357 * General errors and warnings are reported through ws_warning() in
358 * androiddump.
360 * Unfortunately, ws_warning() may be a macro, so we do it by calling
361 * g_logv() with the appropriate arguments.
363 static void
364 androiddump_cmdarg_err(const char *msg_format, va_list ap)
366 ws_logv(LOG_DOMAIN_CAPCHILD, LOG_LEVEL_WARNING, msg_format, ap);
369 static void useSndTimeout(socket_handle_t sock) {
370 int res;
371 #ifdef _WIN32
372 const DWORD socket_timeout = SOCKET_RW_TIMEOUT_MS;
374 res = setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, (const char *) &socket_timeout, (socklen_t)sizeof(socket_timeout));
375 #else
376 const struct timeval socket_timeout = {
377 .tv_sec = SOCKET_RW_TIMEOUT_MS / 1000,
378 .tv_usec = (SOCKET_RW_TIMEOUT_MS % 1000) * 1000
381 res = setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, &socket_timeout, (socklen_t)sizeof(socket_timeout));
382 #endif
383 if (res != 0)
384 ws_debug("Can't set socket timeout, using default");
387 static void useNonBlockingConnectTimeout(socket_handle_t sock) {
388 #ifdef _WIN32
389 unsigned long non_blocking = 1;
391 /* set socket to non-blocking */
392 ioctlsocket(sock, FIONBIO, &non_blocking);
393 #else
394 int flags = fcntl(sock, F_GETFL);
395 fcntl(sock, F_SETFL, flags | O_NONBLOCK);
396 #endif
399 static void useNormalConnectTimeout(socket_handle_t sock) {
400 int res_snd;
401 int res_rcv;
402 #ifdef _WIN32
403 const DWORD socket_timeout = SOCKET_RW_TIMEOUT_MS;
404 unsigned long non_blocking = 0;
406 res_snd = setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, (const char *) &socket_timeout, sizeof(socket_timeout));
407 res_rcv = setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (const char *) &socket_timeout, sizeof(socket_timeout));
408 ioctlsocket(sock, FIONBIO, &non_blocking);
409 #else
410 int flags = fcntl(sock, F_GETFL);
411 fcntl(sock, F_SETFL, flags & ~O_NONBLOCK);
412 const struct timeval socket_timeout = {
413 .tv_sec = SOCKET_RW_TIMEOUT_MS / 1000,
414 .tv_usec = (SOCKET_RW_TIMEOUT_MS % 1000) * 1000
417 res_snd = setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, &socket_timeout, sizeof(socket_timeout));
418 res_rcv = setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &socket_timeout, sizeof(socket_timeout));
419 #endif
420 if (res_snd != 0)
421 ws_debug("Can't set socket timeout, using default");
422 if (res_rcv != 0)
423 ws_debug("Can't set socket timeout, using default");
426 static struct extcap_dumper extcap_dumper_open(char *fifo, int encap) {
427 struct extcap_dumper extcap_dumper;
429 #ifdef ANDROIDDUMP_USE_LIBPCAP
430 pcap_t *pcap;
432 pcap = pcap_open_dead_with_tstamp_precision(encap, PACKET_LENGTH, PCAP_TSTAMP_PRECISION_NANO);
433 extcap_dumper.dumper.pcap = pcap_dump_open(pcap, fifo);
434 if (!extcap_dumper.dumper.pcap) {
435 ws_warning("Can't open %s for saving packets: %s", fifo, pcap_geterr(pcap));
436 pcap_close(pcap);
437 exit(EXIT_CODE_CANNOT_SAVE_LIBPCAP_DUMP);
439 extcap_dumper.encap = encap;
440 if (pcap_dump_flush(extcap_dumper.dumper.pcap) == -1) {
441 ws_warning("Write to %s failed: %s", fifo, g_strerror(errno));
443 #else
444 wtap_dump_params params = WTAP_DUMP_PARAMS_INIT;
445 int file_type_subtype;
446 int err = 0;
447 char *err_info = NULL;
449 wtap_init(false);
451 params.encap = encap;
452 params.snaplen = PACKET_LENGTH;
453 file_type_subtype = wtap_pcap_nsec_file_type_subtype();
454 extcap_dumper.dumper.wtap = wtap_dump_open(fifo, file_type_subtype, WTAP_UNCOMPRESSED, &params, &err, &err_info);
455 if (!extcap_dumper.dumper.wtap) {
456 cfile_dump_open_failure_message(fifo, err, err_info, file_type_subtype);
457 exit(EXIT_CODE_CANNOT_SAVE_WIRETAP_DUMP);
459 extcap_dumper.encap = encap;
460 if (!wtap_dump_flush(extcap_dumper.dumper.wtap, &err)) {
461 cfile_dump_open_failure_message(fifo, err, NULL, file_type_subtype);
462 exit(EXIT_CODE_CANNOT_SAVE_WIRETAP_DUMP);
464 #endif
466 return extcap_dumper;
469 static bool extcap_dumper_dump(struct extcap_dumper extcap_dumper,
470 char *fifo, char *buffer,
471 ssize_t captured_length, ssize_t reported_length,
472 time_t seconds, int nanoseconds) {
473 #ifdef ANDROIDDUMP_USE_LIBPCAP
474 struct pcap_pkthdr pcap_header;
476 pcap_header.caplen = (bpf_u_int32) captured_length;
477 pcap_header.len = (bpf_u_int32) reported_length;
478 pcap_header.ts.tv_sec = seconds;
479 pcap_header.ts.tv_usec = nanoseconds / 1000;
481 pcap_dump((u_char *) extcap_dumper.dumper.pcap, &pcap_header, buffer);
482 if (pcap_dump_flush(extcap_dumper.dumper.pcap) == -1) {
483 ws_warning("Write to %s failed: %s", fifo, g_strerror(errno));
485 #else
486 int err = 0;
487 char *err_info;
488 wtap_rec rec;
490 rec.rec_type = REC_TYPE_PACKET;
491 rec.presence_flags = WTAP_HAS_TS;
492 rec.rec_header.packet_header.caplen = (uint32_t) captured_length;
493 rec.rec_header.packet_header.len = (uint32_t) reported_length;
495 rec.ts.secs = seconds;
496 rec.ts.nsecs = (int) nanoseconds;
498 rec.block = NULL;
500 /* NOTE: Try to handle pseudoheaders manually */
501 if (extcap_dumper.encap == EXTCAP_ENCAP_BLUETOOTH_H4_WITH_PHDR) {
502 uint32_t *direction;
504 SET_DATA(direction, value_u32, buffer)
506 rec.rec_header.packet_header.pseudo_header.bthci.sent = GINT32_FROM_BE(*direction) ? 0 : 1;
508 rec.rec_header.packet_header.len -= (uint32_t)sizeof(own_pcap_bluetooth_h4_header);
509 rec.rec_header.packet_header.caplen -= (uint32_t)sizeof(own_pcap_bluetooth_h4_header);
511 buffer += sizeof(own_pcap_bluetooth_h4_header);
513 rec.rec_header.packet_header.pkt_encap = extcap_dumper.encap;
515 if (!wtap_dump(extcap_dumper.dumper.wtap, &rec, (const uint8_t *) buffer, &err, &err_info)) {
516 cfile_write_failure_message(NULL, fifo, err, err_info, 0,
517 wtap_dump_file_type_subtype(extcap_dumper.dumper.wtap));
518 return false;
521 if (!wtap_dump_flush(extcap_dumper.dumper.wtap, &err)) {
522 cfile_write_failure_message(NULL, fifo, err, NULL, 0,
523 wtap_dump_file_type_subtype(extcap_dumper.dumper.wtap));
524 return false;
526 #endif
528 return true;
532 static socket_handle_t adb_connect(const char *server_ip, unsigned short *server_tcp_port) {
533 socket_handle_t sock;
534 socklen_t length;
535 struct sockaddr_in server;
536 struct sockaddr_in client;
537 int status;
538 #ifndef _WIN32
539 int result;
540 #endif
541 int tries = 0;
543 memset(&server, 0x0, sizeof(server));
545 server.sin_family = AF_INET;
546 server.sin_port = GINT16_TO_BE(*server_tcp_port);
547 ws_inet_pton4(server_ip, (ws_in4_addr *)&(server.sin_addr.s_addr));
549 if ((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET) {
550 ws_warning("Cannot open system TCP socket: %s", strerror(errno));
551 return INVALID_SOCKET;
554 useNonBlockingConnectTimeout(sock);
555 status = connect(sock, (struct sockaddr *) &server, (socklen_t)sizeof(server));
556 #ifdef _WIN32
557 if ((status == SOCKET_ERROR) && (WSAGetLastError() == WSAEWOULDBLOCK)) {
558 #else
559 if ((status == SOCKET_ERROR) && (errno == EINPROGRESS)) {
560 #endif
561 while (tries < SOCKET_CONNECT_TIMEOUT_TRIES) {
562 tries += 1;
563 struct timeval timeout = {
564 .tv_sec = 0,
565 .tv_usec = SOCKET_CONNECT_DELAY_US,
567 fd_set fdset;
568 FD_ZERO(&fdset);
569 FD_SET(sock, &fdset);
570 #ifdef _WIN32
571 if ((select(0, NULL, &fdset, NULL, &timeout) != 0) && (FD_ISSET(sock, &fdset))) {
572 status = 0;
573 break;
574 #else
575 if ((select(sock+1, NULL, &fdset, NULL, &timeout) != 0) && (FD_ISSET(sock, &fdset))) {
576 length = sizeof(result);
577 getsockopt(sock, SOL_SOCKET, SO_ERROR, &result, &length);
578 if (result == 0) {
579 status = 0;
580 } else {
581 ws_debug("Error connecting to ADB: <%s>", strerror(result));
583 break;
584 #endif
585 } else {
586 ws_debug("Try %i: Timeout connecting to ADB", tries);
590 useNormalConnectTimeout(sock);
592 if (status == SOCKET_ERROR) {
593 #if 0
594 /* NOTE: This does not work well - make significant delay while initializing Wireshark.
595 Do fork() then call "adb" also does not make sense, because there is need to
596 do something like sleep(1) to ensure adb is started... system() cannot be used
597 on Windows, because open console window. This helper does not work as expected,
598 so disable it and user must ensure that adb is started (adb start-server,
599 but also all other command start-server automatically)
601 #ifdef _WIN32
602 if (_execlp("adb", "adb", "start-server", NULL)) {
603 #else
604 if (execlp("adb", "adb", "start-server", NULL)) {
605 #endif
606 errmsg("WARNING: Cannot execute system command to start adb: %s", strerror(errno));
607 closesocket(sock);
608 return INVALID_SOCKET;
611 if (connect(sock, (struct sockaddr *) &server, (socklen_t)sizeof(server)) == SOCKET_ERROR) {
612 ws_warning("Cannot connect to ADB: <%s> Please check that adb daemon is running.", strerror(errno));
613 closesocket(sock);
614 return INVALID_SOCKET;
616 #else
617 ws_debug("Cannot connect to ADB: Please check that adb daemon is running.");
618 closesocket(sock);
619 return INVALID_SOCKET;
620 #endif
623 length = sizeof(client);
624 if (getsockname(sock, (struct sockaddr *) &client, &length)) {
625 ws_warning("getsockname: %s", strerror(errno));
626 closesocket(sock);
627 return INVALID_SOCKET;
630 if (length != sizeof(client)) {
631 ws_warning("incorrect length");
632 closesocket(sock);
633 return INVALID_SOCKET;
636 ws_debug("Client port %u", GUINT16_FROM_BE(client.sin_port));
638 return sock;
642 static char *adb_send_and_receive(socket_handle_t sock, const char *adb_service,
643 char *buffer, size_t buffer_length, size_t *data_length) {
644 size_t used_buffer_length;
645 size_t bytes_to_read;
646 uint32_t length;
647 ssize_t result;
648 char status[4];
649 char tmp_buffer;
650 size_t adb_service_length;
652 adb_service_length = strlen(adb_service);
653 if (adb_service_length > INT_MAX) {
654 ws_warning("Service name too long when sending <%s> to ADB daemon", adb_service);
655 if (data_length)
656 *data_length = 0;
657 return NULL;
660 /* 8 bytes of hex length + terminating NUL */
661 if (buffer_length < 9) {
662 ws_warning("Buffer for response too short while sending <%s> to ADB daemon", adb_service);
663 if (data_length)
664 *data_length = 0;
665 return NULL;
668 snprintf(buffer, buffer_length, ADB_HEX4_FORMAT, adb_service_length);
669 result = send(sock, buffer, ADB_HEX4_LEN, 0);
670 if (result < ADB_HEX4_LEN) {
671 ws_warning("Error while sending <%s> length to ADB daemon", adb_service);
672 return NULL;
675 result = send(sock, adb_service, (int) adb_service_length, 0);
676 if (result != (ssize_t) adb_service_length) {
677 ws_warning("Error while sending <%s> to ADB daemon", adb_service);
678 if (data_length)
679 *data_length = 0;
680 return NULL;
683 used_buffer_length = 0;
684 while (used_buffer_length < 8) {
685 bytes_to_read = buffer_length - used_buffer_length;
686 if (bytes_to_read > INT_MAX)
687 bytes_to_read = INT_MAX;
688 result = recv(sock, buffer + used_buffer_length, (int)bytes_to_read, 0);
690 if (result <= 0) {
691 ws_warning("Broken socket connection while fetching reply status for <%s>", adb_service);
692 if (data_length)
693 *data_length = 0;
694 return NULL;
697 used_buffer_length += result;
700 memcpy(status, buffer, 4);
701 tmp_buffer = buffer[8];
702 buffer[8] = '\0';
703 if (!ws_hexstrtou32(buffer + 4, NULL, &length)) {
704 ws_warning("Invalid reply length <%s> while reading reply for <%s>", buffer + 4, adb_service);
705 if (data_length)
706 *data_length = 0;
707 return NULL;
709 buffer[8] = tmp_buffer;
711 if (buffer_length < length + 8) {
712 ws_warning("Buffer for response too short while sending <%s> to ADB daemon", adb_service);
713 if (data_length)
714 *data_length = 0;
715 return NULL;
718 while (used_buffer_length < length + 8) {
719 bytes_to_read = buffer_length - used_buffer_length;
720 if (bytes_to_read > INT_MAX)
721 bytes_to_read = INT_MAX;
722 result = recv(sock, buffer + used_buffer_length, (int)bytes_to_read, 0);
724 if (result <= 0) {
725 ws_warning("Broken socket connection while reading reply for <%s>", adb_service);
726 if (data_length)
727 *data_length = 0;
728 return NULL;
731 used_buffer_length += result;
734 if (data_length)
735 *data_length = used_buffer_length - 8;
737 if (memcmp(status, "OKAY", 4)) {
738 ws_warning("Error while receiving by ADB for <%s>", adb_service);
739 if (data_length)
740 *data_length = 0;
741 return NULL;
744 return buffer + 8;
748 static char *adb_send_and_read(socket_handle_t sock, const char *adb_service, char *buffer,
749 int buffer_length, ssize_t *data_length) {
750 ssize_t used_buffer_length;
751 ssize_t result;
752 char status[4];
753 size_t adb_service_length;
755 adb_service_length = strlen(adb_service);
756 snprintf(buffer, buffer_length, ADB_HEX4_FORMAT, adb_service_length);
758 result = send(sock, buffer, ADB_HEX4_LEN, 0);
759 if (result < ADB_HEX4_LEN) {
760 ws_warning("Error while sending <%s> to ADB daemon", adb_service);
761 return NULL;
764 result = send(sock, adb_service, (int) adb_service_length, 0);
765 if (result != (ssize_t) adb_service_length) {
766 ws_warning("Error while sending <%s> to ADB", adb_service);
767 if (data_length)
768 *data_length = 0;
769 return NULL;
772 used_buffer_length = 0;
773 while (used_buffer_length < 4) {
774 result = recv(sock, buffer + used_buffer_length, (int)(buffer_length - used_buffer_length), 0);
776 if (result <= 0) {
777 ws_warning("Broken socket connection while fetching reply status for <%s>", adb_service);
779 return NULL;
782 used_buffer_length += result;
785 memcpy(status, buffer, 4);
787 while (result > 0) {
788 result= recv(sock, buffer + used_buffer_length, (int)(buffer_length - used_buffer_length), 0);
790 if (result < 0) {
791 ws_warning("Broken socket connection while reading reply for <%s>", adb_service);
793 return NULL;
794 } else if (result == 0) {
795 break;
798 used_buffer_length += result;
801 if (data_length)
802 *data_length = used_buffer_length - 4;
804 if (memcmp(status, "OKAY", 4)) {
805 ws_warning("Error while receiving by ADB for <%s>", adb_service);
806 if (data_length)
807 *data_length = 0;
808 return NULL;
811 return buffer + 4;
815 static int adb_send(socket_handle_t sock, const char *adb_service) {
816 char buffer[5];
817 int used_buffer_length;
818 ssize_t result;
819 size_t adb_service_length;
821 adb_service_length = strlen(adb_service);
822 snprintf(buffer, sizeof(buffer), ADB_HEX4_FORMAT, adb_service_length);
824 result = send(sock, buffer, ADB_HEX4_LEN, 0);
825 if (result < ADB_HEX4_LEN) {
826 ws_warning("Error while sending <%s> to ADB daemon", adb_service);
827 return EXIT_CODE_ERROR_WHILE_SENDING_ADB_PACKET_1;
830 result = send(sock, adb_service, (int) adb_service_length, 0);
831 if (result != (ssize_t) adb_service_length) {
832 ws_warning("Error while sending <%s> to ADB", adb_service);
833 return EXIT_CODE_ERROR_WHILE_SENDING_ADB_PACKET_1;
836 used_buffer_length = 0;
837 while (used_buffer_length < 4) {
838 result = recv(sock, buffer + used_buffer_length, 4 - used_buffer_length, 0);
840 if (result <= 0) {
841 ws_warning("Broken socket connection while fetching reply status for <%s>", adb_service);
843 return EXIT_CODE_ERROR_WHILE_RECEIVING_ADB_PACKET_STATUS;
846 used_buffer_length += (int)result;
849 if (memcmp(buffer, "OKAY", 4)) {
850 ws_debug("Error while receiving by ADB for <%s>", adb_service);
852 return EXIT_CODE_ERROR_WHILE_RECEIVING_ADB_PACKET_DATA;
855 return EXIT_CODE_SUCCESS;
859 static socket_handle_t
860 adb_connect_transport(const char *server_ip, unsigned short *server_tcp_port,
861 const char* serial_number)
863 static const char *const adb_transport_serial_templace = "host:transport:%s";
864 static const char *const adb_transport_any = "host:transport-any";
865 char transport_buf[80];
866 const char* transport = transport_buf;
867 socket_handle_t sock;
868 ssize_t result;
870 sock = adb_connect(server_ip, server_tcp_port);
871 if (sock == INVALID_SOCKET) {
872 ws_warning("Error while connecting to adb server");
873 return sock;
876 if (!serial_number) {
877 transport = adb_transport_any;
878 } else {
879 result = snprintf(transport_buf, sizeof(transport_buf), adb_transport_serial_templace, serial_number);
880 if (result <= 0 || result > (int)sizeof(transport_buf)) {
881 ws_warning("Error while completing adb packet for transport");
882 closesocket(sock);
883 return INVALID_SOCKET;
887 result = adb_send(sock, transport);
888 if (result) {
889 ws_warning("Error while setting adb transport for <%s>", transport_buf);
890 closesocket(sock);
891 return INVALID_SOCKET;
893 return sock;
897 static void new_interface(extcap_parameters * extcap_conf, const char *interface_id,
898 const char *model_name, const char *serial_number, const char *display_name)
900 char *interface = ws_strdup_printf("%s-%s", interface_id, serial_number);
901 char *ifdisplay = ws_strdup_printf("%s %s %s", display_name, model_name, serial_number);
903 if (is_specified_interface(interface, INTERFACE_ANDROID_BLUETOOTH_HCIDUMP) ||
904 is_specified_interface(interface, INTERFACE_ANDROID_BLUETOOTH_EXTERNAL_PARSER) ||
905 is_specified_interface(interface, INTERFACE_ANDROID_BLUETOOTH_BTSNOOP_NET)) {
907 extcap_base_register_interface_ext(extcap_conf, interface, ifdisplay, 99, "BluetoothH4", "Bluetooth HCI UART transport layer plus pseudo-header" );
908 } else if (is_logcat_interface(interface) || is_logcat_text_interface(interface)) {
909 extcap_base_register_interface(extcap_conf, interface, ifdisplay, 252, "Upper PDU" );
910 } else if (is_specified_interface(interface, INTERFACE_ANDROID_TCPDUMP)) {
911 extcap_base_register_interface(extcap_conf, interface, ifdisplay, 1, "Ethernet");
913 g_free(interface);
914 g_free(ifdisplay);
918 static void new_fake_interface_for_list_dlts(extcap_parameters * extcap_conf,
919 const char *ifname)
921 if (is_specified_interface(ifname, INTERFACE_ANDROID_BLUETOOTH_HCIDUMP) ||
922 is_specified_interface(ifname, INTERFACE_ANDROID_BLUETOOTH_EXTERNAL_PARSER) ||
923 is_specified_interface(ifname, INTERFACE_ANDROID_BLUETOOTH_BTSNOOP_NET)) {
924 extcap_base_register_interface_ext(extcap_conf, ifname, ifname, 99, "BluetoothH4", "Bluetooth HCI UART transport layer plus pseudo-header" );
925 } else if (is_logcat_interface(ifname) || is_logcat_text_interface(ifname)) {
926 extcap_base_register_interface(extcap_conf, ifname, ifname, 252, "Upper PDU" );
927 } else if (is_specified_interface(ifname, INTERFACE_ANDROID_TCPDUMP)) {
928 extcap_base_register_interface(extcap_conf, ifname, ifname, 1, "Ethernet");
933 static int add_tcpdump_interfaces(extcap_parameters * extcap_conf, const char *adb_server_ip, unsigned short *adb_server_tcp_port, const char *serial_number)
935 static const char *const adb_tcpdump_list = "shell:tcpdump -D";
936 static const char *const regex_ifaces = "\\d+\\.(?<iface>\\S+)(\\s+?(?:(?:\\(.*\\))*)(\\s*?\\[(?<flags>.*?)\\])?)?";
937 static char recv_buffer[PACKET_LENGTH];
938 char *response;
939 ssize_t data_length;
940 socket_handle_t sock;
941 GRegex* regex = NULL;
942 GError *err = NULL;
943 GMatchInfo *match = NULL;
944 char* tok;
945 char iface_name[80];
946 bool flags_supported;
948 sock = adb_connect_transport(adb_server_ip, adb_server_tcp_port, serial_number);
949 if (sock == INVALID_SOCKET) {
950 ws_warning("Failed to connect to adb server");
951 return EXIT_CODE_GENERIC;
954 response = adb_send_and_read(sock, adb_tcpdump_list, recv_buffer, sizeof(recv_buffer), &data_length);
955 closesocket(sock);
957 if (!response) {
958 ws_warning("Failed to get list of available tcpdump interfaces");
959 return EXIT_CODE_GENERIC;
961 response[data_length] = '\0';
963 regex = g_regex_new(regex_ifaces, G_REGEX_RAW, (GRegexMatchFlags)0, &err);
964 if (!regex) {
965 ws_warning("Failed to compile regex for tcpdump interface matching");
966 return EXIT_CODE_GENERIC;
969 flags_supported = (strstr(response, "[") != 0) && (strstr(response, "]") != 0);
971 tok = strtok(response, "\n");
972 while (tok != NULL) {
973 g_regex_match(regex, tok, (GRegexMatchFlags)0, &match);
974 if (g_match_info_matches(match)) {
975 char *iface = g_match_info_fetch_named(match, "iface");
976 char *flags = g_match_info_fetch_named(match, "flags");
978 if (!flags_supported || (flags && strstr(flags, "Up"))) {
979 snprintf(iface_name, sizeof(iface_name), INTERFACE_ANDROID_TCPDUMP_FORMAT, iface);
980 new_interface(extcap_conf, iface_name, iface, serial_number, "Android tcpdump");
982 g_free(flags);
983 g_free(iface);
985 g_match_info_free(match);
986 tok = strtok(NULL, "\n");
988 g_regex_unref(regex);
989 return 0;
993 static int register_interfaces(extcap_parameters * extcap_conf, const char *adb_server_ip, unsigned short *adb_server_tcp_port) {
994 static char packet[PACKET_LENGTH];
995 static char helpful_packet[PACKET_LENGTH];
996 char check_port_buf[80];
997 char *response;
998 char *device_list;
999 ssize_t data_length;
1000 size_t device_length;
1001 socket_handle_t sock;
1002 const char *adb_check_port_templace = "shell:cat /proc/%s/net/tcp";
1003 const char *adb_devices = "host:devices-l";
1004 const char *adb_api_level = "shell:getprop ro.build.version.sdk";
1005 const char *adb_hcidump_version = "shell:hcidump --version";
1006 const char *adb_ps_droid_bluetooth = "shell:ps droid.bluetooth";
1007 const char *adb_ps_bluetooth_app = "shell:ps com.android.bluetooth";
1008 const char *adb_ps_with_grep = "shell:ps | grep com.android.bluetooth";
1009 const char *adb_ps_all_with_grep = "shell:ps -A | grep com.*android.bluetooth";
1010 char serial_number[SERIAL_NUMBER_LENGTH_MAX];
1011 char model_name[MODEL_NAME_LENGTH_MAX];
1012 int result;
1013 char *pos;
1014 char *i_pos;
1015 char *model_pos;
1016 char *device_pos;
1017 char *prev_pos;
1018 int api_level;
1019 int disable_interface;
1021 /* NOTE: It seems that "adb devices" and "adb shell" closed connection
1022 so cannot send next command after them, there is need to reconnect */
1024 sock = adb_connect(adb_server_ip, adb_server_tcp_port);
1025 if (sock == INVALID_SOCKET)
1026 return EXIT_CODE_INVALID_SOCKET_INTERFACES_LIST;
1028 device_list = adb_send_and_receive(sock, adb_devices, packet, sizeof(packet), &device_length);
1029 closesocket(sock);
1031 if (!device_list) {
1032 ws_warning("Cannot get list of interfaces from devices");
1034 return EXIT_CODE_CANNOT_GET_INTERFACES_LIST;
1037 device_list[device_length] = '\0';
1038 pos = (char *) device_list;
1040 while (pos < (char *) (device_list + device_length)) {
1041 prev_pos = pos;
1042 pos = strchr(pos, ' ');
1043 i_pos = pos;
1044 result = (int) (pos - prev_pos);
1045 pos = strchr(pos, '\n') + 1;
1046 if (result >= (int) sizeof(serial_number)) {
1047 ws_warning("Serial number too long, ignore device");
1048 continue;
1050 memcpy(serial_number, prev_pos, result);
1051 serial_number[result] = '\0';
1053 model_name[0] = '\0';
1054 model_pos = g_strstr_len(i_pos, pos - i_pos, "model:");
1055 if (model_pos) {
1056 device_pos = g_strstr_len(i_pos, pos - i_pos, "device:");
1057 if (device_pos && device_pos - model_pos - 6 - 1 < MODEL_NAME_LENGTH_MAX) {
1058 memcpy(model_name, model_pos + 6, device_pos - model_pos - 6 - 1);
1059 model_name[device_pos - model_pos - 6 - 1] = '\0';
1063 if (model_name[0] == '\0')
1064 strcpy(model_name, "unknown");
1066 ws_debug("Processing device: \"%s\" <%s>" , serial_number, model_name);
1068 /* Function will only add tcpdump interfaces if tcpdump is present on the device */
1069 result = add_tcpdump_interfaces(extcap_conf, adb_server_ip, adb_server_tcp_port, serial_number );
1070 if (result) {
1071 ws_warning("Error while adding tcpdump interfaces");
1074 sock = adb_connect_transport(adb_server_ip, adb_server_tcp_port, serial_number);
1075 if (sock == INVALID_SOCKET) continue;
1077 response = adb_send_and_read(sock, adb_api_level, helpful_packet, sizeof(helpful_packet), &data_length);
1078 closesocket(sock);
1080 if (!response) {
1081 ws_warning("Error on socket: <%s>", helpful_packet);
1082 continue;
1085 response[data_length] = '\0';
1086 api_level = (int) g_ascii_strtoll(response, NULL, 10);
1087 ws_debug("Android API Level for %s is %i", serial_number, api_level);
1089 if (api_level < 21) {
1090 new_interface(extcap_conf, INTERFACE_ANDROID_LOGCAT_MAIN, model_name, serial_number, "Android Logcat Main");
1091 new_interface(extcap_conf, INTERFACE_ANDROID_LOGCAT_SYSTEM, model_name, serial_number, "Android Logcat System");
1092 new_interface(extcap_conf, INTERFACE_ANDROID_LOGCAT_RADIO, model_name, serial_number, "Android Logcat Radio");
1093 new_interface(extcap_conf, INTERFACE_ANDROID_LOGCAT_EVENTS, model_name, serial_number, "Android Logcat Events");
1095 new_interface(extcap_conf, INTERFACE_ANDROID_LOGCAT_TEXT_MAIN, model_name, serial_number, "Android Logcat Main");
1096 new_interface(extcap_conf, INTERFACE_ANDROID_LOGCAT_TEXT_SYSTEM, model_name, serial_number, "Android Logcat System");
1097 new_interface(extcap_conf, INTERFACE_ANDROID_LOGCAT_TEXT_RADIO, model_name, serial_number, "Android Logcat Radio");
1098 new_interface(extcap_conf, INTERFACE_ANDROID_LOGCAT_TEXT_EVENTS, model_name, serial_number, "Android Logcat Events");
1099 } else {
1100 new_interface(extcap_conf, INTERFACE_ANDROID_LOGCAT_TEXT_MAIN, model_name, serial_number, "Android Logcat Main");
1101 new_interface(extcap_conf, INTERFACE_ANDROID_LOGCAT_TEXT_SYSTEM, model_name, serial_number, "Android Logcat System");
1102 new_interface(extcap_conf, INTERFACE_ANDROID_LOGCAT_TEXT_RADIO, model_name, serial_number, "Android Logcat Radio");
1103 new_interface(extcap_conf, INTERFACE_ANDROID_LOGCAT_TEXT_EVENTS, model_name, serial_number, "Android Logcat Events");
1104 new_interface(extcap_conf, INTERFACE_ANDROID_LOGCAT_TEXT_CRASH, model_name, serial_number, "Android Logcat Crash");
1107 if (api_level >= 5 && api_level < 17) {
1108 disable_interface = 0;
1110 sock = adb_connect_transport(adb_server_ip, adb_server_tcp_port, serial_number);
1111 if (sock == INVALID_SOCKET) continue;
1113 response = adb_send_and_read(sock, adb_hcidump_version, helpful_packet, sizeof(helpful_packet), &data_length);
1114 closesocket(sock);
1116 if (!response || data_length < 1) {
1117 ws_warning("Error while getting hcidump version by <%s> (%p len=%"PRIdMAX")",
1118 adb_hcidump_version, (void*)response, (intmax_t)data_length);
1119 ws_debug("Android hcidump version for %s is unknown", serial_number);
1120 disable_interface = 1;
1121 } else {
1122 response[data_length] = '\0';
1124 if (g_ascii_strtoull(response, NULL, 10) == 0) {
1125 ws_debug("Android hcidump version for %s is unknown", serial_number);
1126 disable_interface = 1;
1127 } else {
1128 ws_debug("Android hcidump version for %s is %s", serial_number, response);
1132 if (!disable_interface) {
1133 new_interface(extcap_conf, INTERFACE_ANDROID_BLUETOOTH_HCIDUMP, model_name, serial_number, "Android Bluetooth Hcidump");
1137 if (api_level >= 17 && api_level < 21) {
1138 disable_interface = 0;
1139 sock = adb_connect_transport(adb_server_ip, adb_server_tcp_port, serial_number);
1140 if (sock == INVALID_SOCKET) continue;
1142 response = adb_send_and_read(sock, adb_ps_droid_bluetooth, helpful_packet, sizeof(helpful_packet), &data_length);
1143 closesocket(sock);
1144 if (!response || data_length < 1) {
1145 ws_warning("Error while getting Bluetooth application process id by <%s> "
1146 "(%p len=%"PRIdMAX")", adb_ps_droid_bluetooth, (void*)response, (intmax_t)data_length);
1147 ws_debug( "Android Bluetooth application PID for %s is unknown", serial_number);
1148 disable_interface = 1;
1149 } else {
1150 char *data_str;
1151 char pid[16];
1153 memset(pid, 0, sizeof(pid));
1154 response[data_length] = '\0';
1156 data_str = strchr(response, '\n');
1157 if (data_str && sscanf(data_str, "%*s %15s", pid) == 1) {
1158 ws_debug("Android Bluetooth application PID for %s is %s", serial_number, pid);
1160 result = snprintf(check_port_buf, sizeof(check_port_buf), adb_check_port_templace, pid);
1161 if (result <= 0 || result > (int)sizeof(check_port_buf)) {
1162 ws_warning("Error while completing adb packet");
1163 return EXIT_CODE_BAD_SIZE_OF_ASSEMBLED_ADB_PACKET_6;
1166 sock = adb_connect_transport(adb_server_ip, adb_server_tcp_port, serial_number);
1167 if (sock == INVALID_SOCKET) continue;
1169 response = adb_send_and_read(sock, check_port_buf, helpful_packet, sizeof(helpful_packet), &data_length);
1170 closesocket(sock);
1172 if (!response) {
1173 disable_interface = 1;
1174 } else {
1175 response[data_length] = '\0';
1177 data_str = strchr(response, '\n');
1178 if (data_str && sscanf(data_str, "%*s %15s", pid) == 1 && strlen(pid) > 10 && strcmp(pid + 9, "10EA") == 0) {
1179 ws_debug("Bluedroid External Parser Port for %s is %s", serial_number, pid + 9);
1180 } else {
1181 disable_interface = 1;
1182 ws_debug("Bluedroid External Parser Port for %s is unknown", serial_number);
1185 } else {
1186 disable_interface = 1;
1187 ws_debug("Android Bluetooth application PID for %s is unknown", serial_number);
1191 if (!disable_interface) {
1192 new_interface(extcap_conf, INTERFACE_ANDROID_BLUETOOTH_EXTERNAL_PARSER, model_name, serial_number, "Android Bluetooth External Parser");
1196 if (api_level >= 21) {
1197 const char* ps_cmd;
1198 disable_interface = 0;
1200 if (api_level >= 26) {
1201 ps_cmd = adb_ps_all_with_grep;
1202 } else if (api_level >= 24) {
1203 ps_cmd = adb_ps_with_grep;
1204 } else if (api_level >= 23) {
1205 ps_cmd = adb_ps_bluetooth_app;
1206 } else {
1207 ps_cmd = adb_ps_droid_bluetooth;
1209 sock = adb_connect_transport(adb_server_ip, adb_server_tcp_port, serial_number);
1210 if (sock == INVALID_SOCKET) continue;
1212 response = adb_send_and_read(sock, ps_cmd, helpful_packet, sizeof(helpful_packet), &data_length);
1213 closesocket(sock);
1215 if (!response || data_length < 1) {
1216 ws_warning("Error while getting Bluetooth application process id by <%s> "
1217 "(%p len=%"PRIdMAX")", ps_cmd, (void*)response, (intmax_t)data_length);
1218 ws_debug("Android Bluetooth application PID for %s is unknown", serial_number);
1219 disable_interface = 1;
1220 } else {
1221 char *data_str;
1222 char pid[16];
1224 memset(pid, 0, sizeof(pid));
1225 response[data_length] = '\0';
1227 if (api_level >= 24)
1228 data_str = response;
1229 else
1230 data_str = strchr(response, '\n');
1232 if (data_str && sscanf(data_str, "%*s %15s", pid) == 1) {
1233 ws_debug("Android Bluetooth application PID for %s is %s", serial_number, pid);
1235 result = snprintf(check_port_buf, sizeof(check_port_buf), adb_check_port_templace, pid);
1236 if (result <= 0 || result > (int)sizeof(check_port_buf)) {
1237 ws_warning("Error while completing adb packet");
1238 return EXIT_CODE_BAD_SIZE_OF_ASSEMBLED_ADB_PACKET_9;
1241 sock = adb_connect_transport(adb_server_ip, adb_server_tcp_port, serial_number);
1242 if (sock == INVALID_SOCKET) continue;
1244 response = adb_send_and_read(sock, check_port_buf, helpful_packet, sizeof(helpful_packet), &data_length);
1245 closesocket(sock);
1247 if (!response) {
1248 disable_interface = 1;
1249 } else {
1250 response[data_length] = '\0';
1251 data_str = strtok(response, "\n");
1252 while (data_str != NULL) {
1253 if (sscanf(data_str, "%*s %15s", pid) == 1 && strlen(pid) > 10 && strcmp(pid + 9, "22A8") == 0) {
1254 ws_debug("Btsnoop Net Port for %s is %s", serial_number, pid + 9);
1255 break;
1257 data_str = strtok(NULL, "\n");
1259 if (data_str == NULL) {
1260 disable_interface = 1;
1261 ws_debug("Btsnoop Net Port for %s is unknown", serial_number);
1264 } else {
1265 disable_interface = 1;
1266 ws_debug("Android Bluetooth application PID for %s is unknown", serial_number);
1270 if (!disable_interface) {
1271 new_interface(extcap_conf, INTERFACE_ANDROID_BLUETOOTH_BTSNOOP_NET, model_name, serial_number, "Android Bluetooth Btsnoop Net");
1276 return EXIT_CODE_SUCCESS;
1279 static int list_config(char *interface) {
1280 int ret = EXIT_CODE_INVALID_INTERFACE;
1281 unsigned inc = 0;
1283 if (!interface) {
1284 ws_warning("No interface specified.");
1285 return EXIT_CODE_NO_INTERFACE_SPECIFIED;
1288 if (is_specified_interface(interface, INTERFACE_ANDROID_BLUETOOTH_EXTERNAL_PARSER)) {
1289 printf("arg {number=%u}{call=--adb-server-ip}{display=ADB Server IP Address}{type=string}{default=127.0.0.1}\n", inc++);
1290 printf("arg {number=%u}{call=--adb-server-tcp-port}{display=ADB Server TCP Port}{type=integer}{range=0,65535}{default=5037}\n", inc++);
1291 printf("arg {number=%u}{call=--bt-server-tcp-port}{display=Bluetooth Server TCP Port}{type=integer}{range=0,65535}{default=4330}\n", inc++);
1292 printf("arg {number=%u}{call=--bt-forward-socket}{display=Forward Bluetooth Socket}{type=boolean}{default=false}\n", inc++);
1293 printf("arg {number=%u}{call=--bt-local-ip}{display=Bluetooth Local IP Address}{type=string}{default=127.0.0.1}\n", inc++);
1294 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++);
1295 ret = EXIT_CODE_SUCCESS;
1296 } else if (is_specified_interface(interface, INTERFACE_ANDROID_BLUETOOTH_HCIDUMP) ||
1297 is_specified_interface(interface, INTERFACE_ANDROID_BLUETOOTH_BTSNOOP_NET) ||
1298 is_specified_interface(interface, INTERFACE_ANDROID_TCPDUMP)) {
1299 printf("arg {number=%u}{call=--adb-server-ip}{display=ADB Server IP Address}{type=string}{default=127.0.0.1}\n", inc++);
1300 printf("arg {number=%u}{call=--adb-server-tcp-port}{display=ADB Server TCP Port}{type=integer}{range=0,65535}{default=5037}\n", inc++);
1301 ret = EXIT_CODE_SUCCESS;
1302 } else if (is_logcat_interface(interface)) {
1303 printf("arg {number=%u}{call=--adb-server-ip}{display=ADB Server IP Address}{type=string}{default=127.0.0.1}\n", inc++);
1304 printf("arg {number=%u}{call=--adb-server-tcp-port}{display=ADB Server TCP Port}{type=integer}{range=0,65535}{default=5037}\n", inc++);
1305 printf("arg {number=%u}{call=--logcat-text}{display=Use text logcat}{type=boolean}{default=false}\n", inc++);
1306 printf("arg {number=%u}{call=--logcat-ignore-log-buffer}{display=Ignore log buffer}{type=boolean}{default=false}\n", inc++);
1307 printf("arg {number=%u}{call=--logcat-custom-options}{display=Custom logcat parameters}{type=string}\n", inc++);
1308 ret = EXIT_CODE_SUCCESS;
1309 } else if (is_logcat_text_interface(interface)) {
1310 printf("arg {number=%u}{call=--adb-server-ip}{display=ADB Server IP Address}{type=string}{default=127.0.0.1}\n", inc++);
1311 printf("arg {number=%u}{call=--adb-server-tcp-port}{display=ADB Server TCP Port}{type=integer}{range=0,65535}{default=5037}\n", inc++);
1312 printf("arg {number=%u}{call=--logcat-ignore-log-buffer}{display=Ignore log buffer}{type=boolean}{default=false}\n", inc++);
1313 printf("arg {number=%u}{call=--logcat-custom-options}{display=Custom logcat parameters}{type=string}\n", inc++);
1314 ret = EXIT_CODE_SUCCESS;
1317 if (ret != EXIT_CODE_SUCCESS)
1318 ws_warning("Invalid interface: <%s>", interface);
1319 else
1320 extcap_config_debug(&inc);
1322 return ret;
1325 /*----------------------------------------------------------------------------*/
1326 /* Android Bluetooth Hcidump */
1327 /*----------------------------------------------------------------------------*/
1329 static int capture_android_bluetooth_hcidump(char *interface, char *fifo,
1330 const char *adb_server_ip, unsigned short *adb_server_tcp_port) {
1331 struct extcap_dumper extcap_dumper;
1332 static char data[PACKET_LENGTH];
1333 static char packet[PACKET_LENGTH];
1334 ssize_t length;
1335 ssize_t used_buffer_length = 0;
1336 socket_handle_t sock = INVALID_SOCKET;
1337 const char *adb_shell_hcidump = "shell:hcidump -R -t";
1338 const char *adb_shell_su_hcidump = "shell:su -c hcidump -R -t";
1339 int result;
1340 char *serial_number;
1341 time_t ts = 0;
1342 unsigned int captured_length;
1343 int64_t hex;
1344 char *hex_data;
1345 char *new_hex_data;
1346 own_pcap_bluetooth_h4_header *h4_header;
1347 int64_t raw_length = 0;
1348 int64_t frame_length;
1349 int ms = 0;
1350 struct tm date;
1351 char direction_character;
1353 SET_DATA(h4_header, value_own_pcap_bluetooth_h4_header, packet);
1355 extcap_dumper = extcap_dumper_open(fifo, EXTCAP_ENCAP_BLUETOOTH_H4_WITH_PHDR);
1357 serial_number = get_serial_from_interface(interface);
1358 sock = adb_connect_transport(adb_server_ip, adb_server_tcp_port, serial_number);
1359 if (sock == INVALID_SOCKET)
1360 return EXIT_CODE_INVALID_SOCKET_3;
1362 result = adb_send(sock, adb_shell_hcidump);
1363 if (result) {
1364 ws_warning("Error while starting capture by sending command: %s", adb_shell_hcidump);
1365 closesocket(sock);
1366 return EXIT_CODE_GENERIC;
1369 while (endless_loop) {
1370 char *i_position;
1372 errno = 0;
1373 length = recv(sock, data + used_buffer_length, (int)(PACKET_LENGTH - used_buffer_length), 0);
1374 if (errno == EAGAIN
1375 #if EWOULDBLOCK != EAGAIN
1376 || errno == EWOULDBLOCK
1377 #endif
1379 continue;
1381 else if (errno != 0) {
1382 ws_warning("ERROR capture: %s", strerror(errno));
1383 closesocket(sock);
1384 return EXIT_CODE_GENERIC;
1387 if (length <= 0) {
1388 ws_warning("Broken socket connection.");
1389 closesocket(sock);
1390 return EXIT_CODE_GENERIC;
1393 used_buffer_length += length;
1394 i_position = (char *) memchr(data, '\n', used_buffer_length);
1395 if (i_position && i_position < data + used_buffer_length) {
1396 char *state_line_position = i_position + 1;
1398 if (!strncmp(data, "/system/bin/sh: hcidump: not found", 34)) {
1399 ws_warning("Command not found for <%s>", adb_shell_hcidump);
1400 closesocket(sock);
1401 return EXIT_CODE_GENERIC;
1404 i_position = (char *) memchr(i_position + 1, '\n', used_buffer_length);
1405 if (i_position) {
1406 i_position += 1;
1407 if (!strncmp(state_line_position, "Can't access device: Permission denied", 38)) {
1408 ws_warning("No permission for command <%s>", adb_shell_hcidump);
1409 used_buffer_length = 0;
1410 closesocket(sock);
1411 sock = INVALID_SOCKET;
1412 break;
1414 memmove(data, i_position, used_buffer_length - (i_position - data));
1415 used_buffer_length = used_buffer_length - (ssize_t)(i_position - data);
1416 break;
1421 if (sock == INVALID_SOCKET) {
1422 sock = adb_connect_transport(adb_server_ip, adb_server_tcp_port, serial_number);
1423 if (sock == INVALID_SOCKET)
1424 return EXIT_CODE_INVALID_SOCKET_4;
1426 result = adb_send(sock, adb_shell_su_hcidump);
1427 if (result) {
1428 ws_warning("Error while starting capture by sending command: <%s>", adb_shell_su_hcidump);
1429 closesocket(sock);
1430 return EXIT_CODE_GENERIC;
1433 used_buffer_length = 0;
1434 while (endless_loop) {
1435 char *i_position;
1437 errno = 0;
1438 length = recv(sock, data + used_buffer_length, (int)(PACKET_LENGTH - used_buffer_length), 0);
1439 if (errno == EAGAIN
1440 #if EWOULDBLOCK != EAGAIN
1441 || errno == EWOULDBLOCK
1442 #endif
1444 continue;
1446 else if (errno != 0) {
1447 ws_warning("ERROR capture: %s", strerror(errno));
1448 closesocket(sock);
1449 return EXIT_CODE_GENERIC;
1452 if (length <= 0) {
1453 ws_warning("Broken socket connection.");
1454 closesocket(sock);
1455 return EXIT_CODE_GENERIC;
1458 used_buffer_length += length;
1459 i_position = (char *) memchr(data, '\n', used_buffer_length);
1460 if (i_position && i_position < data + used_buffer_length) {
1461 if (!strncmp(data, "/system/bin/sh: su: not found", 29)) {
1462 ws_warning("Command 'su' not found for <%s>", adb_shell_su_hcidump);
1463 closesocket(sock);
1464 return EXIT_CODE_GENERIC;
1467 i_position = (char *) memchr(i_position + 1, '\n', used_buffer_length);
1468 if (i_position) {
1469 i_position += 1;
1470 memmove(data, i_position, used_buffer_length - (i_position - data));
1471 used_buffer_length = used_buffer_length - (ssize_t)(i_position - data);
1472 break;
1478 while (endless_loop) {
1479 errno = 0;
1480 length = recv(sock, data + used_buffer_length, (int)(PACKET_LENGTH - used_buffer_length), 0);
1481 if (errno == EAGAIN
1482 #if EWOULDBLOCK != EAGAIN
1483 || errno == EWOULDBLOCK
1484 #endif
1486 continue;
1488 else if (errno != 0) {
1489 ws_warning("ERROR capture: %s", strerror(errno));
1490 closesocket(sock);
1491 return EXIT_CODE_GENERIC;
1494 if (length <= 0) {
1495 ws_warning("Broken socket connection.");
1496 closesocket(sock);
1497 return EXIT_CODE_GENERIC;
1500 while (endless_loop) {
1501 if (used_buffer_length + length >= 1) {
1502 hex_data = data + 29;
1503 hex = g_ascii_strtoll(hex_data, &new_hex_data, 16);
1505 if ((hex == 0x01 && used_buffer_length + length >= 4) ||
1506 (hex == 0x02 && used_buffer_length + length >= 5) ||
1507 (hex == 0x04 && used_buffer_length + length >= 3)) {
1509 if (hex == 0x01) {
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));
1514 closesocket(sock);
1515 return EXIT_CODE_GENERIC;
1518 hex_data = new_hex_data;
1519 hex = g_ascii_strtoll(hex_data, &new_hex_data, 16);
1520 if (hex < 0 || hex >= 256 || hex_data == new_hex_data) {
1521 ws_warning("data format %s", strerror(errno));
1522 closesocket(sock);
1523 return EXIT_CODE_GENERIC;
1526 hex_data = new_hex_data;
1527 hex = g_ascii_strtoll(hex_data, &new_hex_data, 16);
1529 raw_length = hex + 4;
1530 } else if (hex == 0x04) {
1531 hex_data = new_hex_data;
1532 hex = g_ascii_strtoll(hex_data, &new_hex_data, 16);
1533 if (hex < 0 || hex >= 256 || hex_data == new_hex_data) {
1534 ws_warning("data format %s", strerror(errno));
1535 closesocket(sock);
1536 return EXIT_CODE_GENERIC;
1539 hex_data = new_hex_data;
1540 hex = g_ascii_strtoll(hex_data, &new_hex_data, 16);
1542 raw_length = hex + 3;
1543 } else if (hex == 0x02) {
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));
1548 closesocket(sock);
1549 return EXIT_CODE_GENERIC;
1552 hex_data = new_hex_data;
1553 hex = g_ascii_strtoll(hex_data, &new_hex_data, 16);
1554 if (hex < 0 || hex >= 256 || hex_data == new_hex_data) {
1555 ws_warning("data format %s", strerror(errno));
1556 closesocket(sock);
1557 return EXIT_CODE_GENERIC;
1560 hex_data = new_hex_data;
1561 hex = g_ascii_strtoll(hex_data, &new_hex_data, 16);
1562 raw_length = hex + 5;
1564 hex_data = new_hex_data;
1565 hex = g_ascii_strtoll(hex_data, &new_hex_data, 16);
1566 raw_length += hex << 8;
1569 } else {
1570 ws_warning("bad raw stream");
1571 closesocket(sock);
1572 return EXIT_CODE_GENERIC;
1574 } else {
1575 used_buffer_length += length;
1576 break;
1579 frame_length = raw_length * 3 + (raw_length / 20) * 4 + ((raw_length % 20) ? 2 : -2) + 29;
1581 if ((used_buffer_length + length) < frame_length) {
1582 used_buffer_length += length;
1583 break;
1586 if (8 == sscanf(data, "%04d-%02d-%02d %02d:%02d:%02d.%06d %c",
1587 &date.tm_year, &date.tm_mon, &date.tm_mday, &date.tm_hour,
1588 &date.tm_min, &date.tm_sec, &ms, &direction_character)) {
1590 ws_debug("time %04d-%02d-%02d %02d:%02d:%02d.%06d %c",
1591 date.tm_year, date.tm_mon, date.tm_mday, date.tm_hour,
1592 date.tm_min, date.tm_sec, ms, direction_character);
1593 date.tm_mon -= 1;
1594 date.tm_year -= 1900;
1595 date.tm_isdst = -1;
1596 ts = mktime(&date);
1598 new_hex_data = data + 29;
1601 captured_length = 0;
1603 while ((long)(new_hex_data - data + sizeof(own_pcap_bluetooth_h4_header)) < frame_length) {
1604 hex_data = new_hex_data;
1605 hex = g_ascii_strtoll(hex_data, &new_hex_data, 16);
1607 packet[sizeof(own_pcap_bluetooth_h4_header) + captured_length] = (char) hex;
1608 captured_length += 1;
1611 h4_header->direction = GINT32_TO_BE(direction_character == '>');
1613 endless_loop = extcap_dumper_dump(extcap_dumper, fifo, packet,
1614 captured_length + sizeof(own_pcap_bluetooth_h4_header),
1615 captured_length + sizeof(own_pcap_bluetooth_h4_header),
1617 ms * 1000);
1619 memmove(data, data + frame_length, (size_t)(used_buffer_length + length - frame_length));
1620 used_buffer_length = (ssize_t)(used_buffer_length + length - frame_length);
1621 length = 0;
1625 closesocket(sock);
1626 return EXIT_CODE_SUCCESS;
1629 /*----------------------------------------------------------------------------*/
1630 /* Android Bluetooth External Parser */
1631 /*----------------------------------------------------------------------------*/
1633 #define BLUEDROID_H4_PACKET_TYPE 0
1634 #define BLUEDROID_TIMESTAMP_SIZE 8
1635 #define BLUEDROID_H4_SIZE 1
1637 static const uint64_t BLUEDROID_TIMESTAMP_BASE = UINT64_C(0x00dcddb30f2f8000);
1639 #define BLUEDROID_H4_PACKET_TYPE_HCI_CMD 0x01
1640 #define BLUEDROID_H4_PACKET_TYPE_ACL 0x02
1641 #define BLUEDROID_H4_PACKET_TYPE_SCO 0x03
1642 #define BLUEDROID_H4_PACKET_TYPE_HCI_EVT 0x04
1644 #define BLUEDROID_DIRECTION_SENT 0
1645 #define BLUEDROID_DIRECTION_RECV 1
1647 static int adb_forward(char *serial_number, const char *adb_server_ip, unsigned short *adb_server_tcp_port,
1648 unsigned short local_tcp_port, unsigned short server_tcp_port) {
1649 socket_handle_t sock;
1650 int result;
1651 static char helpful_packet[PACKET_LENGTH];
1652 static const char *adb_forward_template = "%s%s:forward:tcp:%05u;tcp:%05u";
1654 sock = adb_connect(adb_server_ip, adb_server_tcp_port);
1655 if (sock == INVALID_SOCKET)
1656 return EXIT_CODE_INVALID_SOCKET_5;
1658 result = snprintf(helpful_packet, PACKET_LENGTH, adb_forward_template, (serial_number) ? "host-serial:" : "host", (serial_number) ? serial_number: "", local_tcp_port, server_tcp_port);
1659 if (result <= 0 || result > PACKET_LENGTH) {
1660 ws_warning("Error while completing adb packet");
1661 closesocket(sock);
1662 return EXIT_CODE_BAD_SIZE_OF_ASSEMBLED_ADB_PACKET_12;
1665 result = adb_send(sock, helpful_packet);
1666 closesocket(sock);
1668 return result;
1671 static int capture_android_bluetooth_external_parser(char *interface,
1672 char *fifo, const char *adb_server_ip, unsigned short *adb_server_tcp_port,
1673 unsigned short *bt_server_tcp_port, unsigned int bt_forward_socket, const char *bt_local_ip,
1674 unsigned short *bt_local_tcp_port) {
1675 struct extcap_dumper extcap_dumper;
1676 static char buffer[PACKET_LENGTH];
1677 uint64_t *timestamp;
1678 char *packet = buffer + BLUEDROID_TIMESTAMP_SIZE - sizeof(own_pcap_bluetooth_h4_header); /* skip timestamp (8 bytes) and reuse its space for header */
1679 own_pcap_bluetooth_h4_header *h4_header;
1680 uint8_t *payload = packet + sizeof(own_pcap_bluetooth_h4_header);
1681 const char *adb_tcp_bluedroid_external_parser_template = "tcp:%05u";
1682 socklen_t slen;
1683 ssize_t length;
1684 ssize_t used_buffer_length = 0;
1685 uint64_t ts;
1686 socket_handle_t sock;
1687 struct sockaddr_in server;
1688 int captured_length;
1689 char *serial_number;
1690 static unsigned int id = 1;
1691 struct sockaddr_in client;
1693 SET_DATA(timestamp, value_u64, buffer);
1694 SET_DATA(h4_header, value_own_pcap_bluetooth_h4_header, packet);
1696 extcap_dumper = extcap_dumper_open(fifo, EXTCAP_ENCAP_BLUETOOTH_H4_WITH_PHDR);
1697 serial_number = get_serial_from_interface(interface);
1699 if (bt_forward_socket) {
1700 if ((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET) {
1701 ws_warning("Cannot open system TCP socket: %s", strerror(errno));
1702 return EXIT_CODE_GENERIC;
1705 ws_debug("Using config: Server TCP Port=%u, Local IP=%s, Local TCP Port=%u",
1706 *bt_server_tcp_port, bt_local_ip, *bt_local_tcp_port);
1708 if (*bt_local_tcp_port != 0) {
1709 int result;
1711 result = adb_forward(serial_number, adb_server_ip, adb_server_tcp_port, *bt_local_tcp_port, *bt_server_tcp_port);
1712 ws_debug("DO: adb forward tcp:%u (local) tcp:%u (remote) result=%i",
1713 *bt_local_tcp_port, *bt_server_tcp_port, result);
1716 memset(&server, 0 , sizeof(server));
1717 server.sin_family = AF_INET;
1718 server.sin_port = GINT16_TO_BE(*bt_local_tcp_port);
1719 ws_inet_pton4(bt_local_ip, (ws_in4_addr *)&(server.sin_addr.s_addr));
1721 useSndTimeout(sock);
1723 if (connect(sock, (struct sockaddr *) &server, sizeof(server)) == SOCKET_ERROR) {
1724 ws_warning("<%s> Please check that adb daemon is running.", strerror(errno));
1725 closesocket(sock);
1726 return EXIT_CODE_GENERIC;
1729 slen = (socklen_t)sizeof(client);
1730 if (getsockname(sock, (struct sockaddr *) &client, &slen)) {
1731 ws_warning("getsockname: %s", strerror(errno));
1732 closesocket(sock);
1733 return EXIT_CODE_GENERIC;
1736 if (slen != sizeof(client)) {
1737 ws_warning("incorrect length");
1738 closesocket(sock);
1739 return EXIT_CODE_GENERIC;
1742 ws_debug("Client port %u", GUINT16_FROM_BE(client.sin_port));
1743 } else {
1744 int result;
1746 sock = adb_connect_transport(adb_server_ip, adb_server_tcp_port, serial_number);
1747 if (sock == INVALID_SOCKET)
1748 return EXIT_CODE_INVALID_SOCKET_6;
1750 result = snprintf((char *) buffer, PACKET_LENGTH, adb_tcp_bluedroid_external_parser_template, *bt_server_tcp_port);
1751 if (result <= 0 || result > PACKET_LENGTH) {
1752 ws_warning("Error while completing adb packet");
1753 closesocket(sock);
1754 return EXIT_CODE_BAD_SIZE_OF_ASSEMBLED_ADB_PACKET_14;
1757 result = adb_send(sock, buffer);
1758 if (result) {
1759 ws_warning("Error while forwarding adb port");
1760 closesocket(sock);
1761 return EXIT_CODE_GENERIC;
1765 while (endless_loop) {
1766 errno = 0;
1767 length = recv(sock, buffer + used_buffer_length, (int)(PACKET_LENGTH - used_buffer_length), 0);
1768 if (errno == EAGAIN
1769 #if EWOULDBLOCK != EAGAIN
1770 || errno == EWOULDBLOCK
1771 #endif
1773 continue;
1775 else if (errno != 0) {
1776 ws_warning("ERROR capture: %s", strerror(errno));
1777 closesocket(sock);
1778 return EXIT_CODE_GENERIC;
1781 if (length <= 0) {
1782 if (bt_forward_socket) {
1783 /* NOTE: Workaround... It seems that Bluedroid is slower and we can connect to socket that are not really ready... */
1784 ws_warning("Broken socket connection. Try reconnect.");
1785 closesocket(sock);
1787 if ((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET) {
1788 ws_warning("%s", strerror(errno));
1789 return EXIT_CODE_GENERIC;
1792 server.sin_family = AF_INET;
1793 server.sin_port = GINT16_TO_BE(*bt_local_tcp_port);
1794 ws_inet_pton4(bt_local_ip, (ws_in4_addr *)&(server.sin_addr.s_addr));
1796 useSndTimeout(sock);
1798 if (connect(sock, (struct sockaddr *) &server, sizeof(server)) == SOCKET_ERROR) {
1799 ws_warning("ERROR reconnect: <%s> Please check that adb daemon is running.", strerror(errno));
1800 closesocket(sock);
1801 return EXIT_CODE_GENERIC;
1803 } else {
1804 ws_warning("Broken socket connection.");
1805 closesocket(sock);
1806 return EXIT_CODE_GENERIC;
1809 continue;
1812 used_buffer_length += length;
1814 ws_debug("Received: length=%"PRIdMAX, (intmax_t)length);
1816 while (((payload[BLUEDROID_H4_PACKET_TYPE] == BLUEDROID_H4_PACKET_TYPE_HCI_CMD || payload[BLUEDROID_H4_PACKET_TYPE] == BLUEDROID_H4_PACKET_TYPE_SCO) &&
1817 used_buffer_length >= BLUEDROID_TIMESTAMP_SIZE + BLUEDROID_H4_SIZE + 2 + 1 &&
1818 BLUEDROID_TIMESTAMP_SIZE + BLUEDROID_H4_SIZE + 2 + payload[BLUEDROID_H4_SIZE + 2] + 1 <= used_buffer_length) ||
1819 (payload[BLUEDROID_H4_PACKET_TYPE] == BLUEDROID_H4_PACKET_TYPE_ACL &&
1820 used_buffer_length >= BLUEDROID_TIMESTAMP_SIZE + BLUEDROID_H4_SIZE + 2 + 2 &&
1821 BLUEDROID_TIMESTAMP_SIZE + BLUEDROID_H4_SIZE + 2 + payload[BLUEDROID_H4_SIZE + 2] + (payload[BLUEDROID_H4_SIZE + 2 + 1] << 8) + 2 <= used_buffer_length) ||
1822 (payload[BLUEDROID_H4_PACKET_TYPE] == BLUEDROID_H4_PACKET_TYPE_SCO &&
1823 used_buffer_length >= BLUEDROID_TIMESTAMP_SIZE + BLUEDROID_H4_SIZE + 2 + 1 &&
1824 BLUEDROID_TIMESTAMP_SIZE + BLUEDROID_H4_SIZE + 2 + payload[BLUEDROID_H4_SIZE + 2] + 1 <= used_buffer_length) ||
1825 (payload[BLUEDROID_H4_PACKET_TYPE] == BLUEDROID_H4_PACKET_TYPE_HCI_EVT &&
1826 used_buffer_length >= BLUEDROID_TIMESTAMP_SIZE + BLUEDROID_H4_SIZE + 1 + 1 &&
1827 BLUEDROID_TIMESTAMP_SIZE + BLUEDROID_H4_SIZE + 1 + payload[BLUEDROID_H4_SIZE + 1] + 1 <= used_buffer_length)) {
1829 ts = GINT64_FROM_BE(*timestamp);
1831 switch (payload[BLUEDROID_H4_PACKET_TYPE]) {
1832 case BLUEDROID_H4_PACKET_TYPE_HCI_CMD:
1833 h4_header->direction = GINT32_TO_BE(BLUEDROID_DIRECTION_SENT);
1835 captured_length = (unsigned int)sizeof(own_pcap_bluetooth_h4_header) + payload[3] + 4;
1837 length = sizeof(own_pcap_bluetooth_h4_header) + BLUEDROID_H4_SIZE + 2 + 1 + payload[3];
1839 break;
1840 case BLUEDROID_H4_PACKET_TYPE_ACL:
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] + (payload[3 + 1] << 8) + 5;
1845 length = sizeof(own_pcap_bluetooth_h4_header) + BLUEDROID_H4_SIZE + 2 + 2 + payload[3] + (ssize_t)(payload[3 + 1] << 8);
1847 break;
1848 case BLUEDROID_H4_PACKET_TYPE_SCO:
1849 h4_header->direction = (payload[2] & 0x80) ? GINT32_TO_BE(BLUEDROID_DIRECTION_RECV) : GINT32_TO_BE(BLUEDROID_DIRECTION_SENT);
1851 captured_length = (unsigned int)sizeof(own_pcap_bluetooth_h4_header) + payload[3] + 4;
1853 length = sizeof(own_pcap_bluetooth_h4_header) + BLUEDROID_H4_SIZE + 2 + 1 + payload[3];
1855 break;
1856 case BLUEDROID_H4_PACKET_TYPE_HCI_EVT:
1857 h4_header->direction = GINT32_TO_BE(BLUEDROID_DIRECTION_RECV);
1859 captured_length = (unsigned int)sizeof(own_pcap_bluetooth_h4_header) + payload[2] + 3;
1861 length = sizeof(own_pcap_bluetooth_h4_header) + BLUEDROID_H4_SIZE + 1 + 1 + payload[2];
1863 break;
1864 default:
1865 ws_warning("Invalid stream");
1866 closesocket(sock);
1867 return EXIT_CODE_GENERIC;
1870 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]);
1871 if (payload[BLUEDROID_H4_PACKET_TYPE] == BLUEDROID_H4_PACKET_TYPE_HCI_EVT)
1872 ws_debug("\t Packet: %02x %02x %02x", (unsigned int) payload[0], (unsigned int) payload[1], (unsigned int)payload[2]);
1873 id +=1;
1875 ts -= BLUEDROID_TIMESTAMP_BASE;
1877 endless_loop = extcap_dumper_dump(extcap_dumper, fifo, packet,
1878 captured_length,
1879 captured_length,
1880 (uint32_t)(ts / 1000000),
1881 ((uint32_t)(ts % 1000000)) * 1000);
1883 used_buffer_length -= length - sizeof(own_pcap_bluetooth_h4_header) + BLUEDROID_TIMESTAMP_SIZE;
1884 if (used_buffer_length < 0) {
1885 ws_warning("Internal Negative used buffer length.");
1886 closesocket(sock);
1887 return EXIT_CODE_GENERIC;
1889 memmove(buffer, packet + length, used_buffer_length);
1893 closesocket(sock);
1894 return EXIT_CODE_SUCCESS;
1897 /*----------------------------------------------------------------------------*/
1898 /* Android Btsnoop Net */
1899 /*----------------------------------------------------------------------------*/
1901 static int capture_android_bluetooth_btsnoop_net(char *interface, char *fifo,
1902 const char *adb_server_ip, unsigned short *adb_server_tcp_port) {
1903 struct extcap_dumper extcap_dumper;
1904 static char packet[PACKET_LENGTH];
1905 ssize_t length;
1906 ssize_t used_buffer_length = 0;
1907 socket_handle_t sock;
1908 const char *adb_tcp_btsnoop_net = "tcp:8872";
1909 int result;
1910 char *serial_number;
1911 uint64_t ts;
1912 static const uint64_t BTSNOOP_TIMESTAMP_BASE = UINT64_C(0x00dcddb30f2f8000);
1913 uint32_t *reported_length;
1914 uint32_t *captured_length;
1915 uint32_t *flags;
1916 /* uint32_t *cumulative_dropped_packets; */
1917 uint64_t *timestamp;
1918 char *payload = packet + sizeof(own_pcap_bluetooth_h4_header) + 24;
1919 own_pcap_bluetooth_h4_header *h4_header;
1921 SET_DATA(reported_length, value_u32, packet + sizeof(own_pcap_bluetooth_h4_header) + 0);
1922 SET_DATA(captured_length, value_u32, packet + sizeof(own_pcap_bluetooth_h4_header) + 4);
1923 SET_DATA(flags, value_u32, packet + sizeof(own_pcap_bluetooth_h4_header) + 8);
1924 /* SET_DATA(cumulative_dropped_packets, value_u32, packet + sizeof(own_pcap_bluetooth_h4_header) + 12); */
1925 SET_DATA(timestamp, value_u64, packet + sizeof(own_pcap_bluetooth_h4_header) + 16);
1926 SET_DATA(h4_header, value_own_pcap_bluetooth_h4_header, payload - sizeof(own_pcap_bluetooth_h4_header));
1928 extcap_dumper = extcap_dumper_open(fifo, EXTCAP_ENCAP_BLUETOOTH_H4_WITH_PHDR);
1929 serial_number = get_serial_from_interface(interface);
1930 sock = adb_connect_transport(adb_server_ip, adb_server_tcp_port, serial_number);
1931 if (sock == INVALID_SOCKET)
1932 return EXIT_CODE_INVALID_SOCKET_7;
1934 result = adb_send(sock, adb_tcp_btsnoop_net);
1935 if (result) {
1936 ws_warning("Error while sending command <%s>", adb_tcp_btsnoop_net);
1937 closesocket(sock);
1938 return EXIT_CODE_ERROR_WHILE_SENDING_ADB_PACKET_2;
1941 /* Read "btsnoop" header - 16 bytes */
1942 while (used_buffer_length < BTSNOOP_HDR_LEN) {
1943 length = recv(sock, packet + used_buffer_length, (int)(BTSNOOP_HDR_LEN - used_buffer_length), 0);
1944 if (length <= 0) {
1945 ws_warning("Broken socket connection.");
1946 closesocket(sock);
1947 return EXIT_CODE_GENERIC;
1949 used_buffer_length += length;
1951 used_buffer_length = 0;
1953 while (endless_loop) {
1954 errno = 0;
1955 length = recv(sock, packet + used_buffer_length + sizeof(own_pcap_bluetooth_h4_header),
1956 (int)(PACKET_LENGTH - sizeof(own_pcap_bluetooth_h4_header) - used_buffer_length), 0);
1957 if (errno == EAGAIN
1958 #if EWOULDBLOCK != EAGAIN
1959 || errno == EWOULDBLOCK
1960 #endif
1962 continue;
1964 else if (errno != 0) {
1965 ws_warning("ERROR capture: %s", strerror(errno));
1966 closesocket(sock);
1967 return EXIT_CODE_GENERIC;
1970 if (length <= 0) {
1971 ws_warning("Broken socket connection.");
1972 closesocket(sock);
1973 return EXIT_CODE_GENERIC;
1976 used_buffer_length += length;
1978 while (used_buffer_length >= 24 &&
1979 used_buffer_length >= (int) (24 + GINT32_FROM_BE(*captured_length))) {
1980 int32_t direction;
1982 ts = GINT64_FROM_BE(*timestamp);
1983 ts -= BTSNOOP_TIMESTAMP_BASE;
1985 direction = GINT32_FROM_BE(*flags) & 0x01;
1986 h4_header->direction = GINT32_TO_BE(direction);
1988 endless_loop = extcap_dumper_dump(extcap_dumper, fifo,
1989 payload - sizeof(own_pcap_bluetooth_h4_header),
1990 GINT32_FROM_BE(*captured_length) + sizeof(own_pcap_bluetooth_h4_header),
1991 GINT32_FROM_BE(*reported_length) + sizeof(own_pcap_bluetooth_h4_header),
1992 (uint32_t)(ts / 1000000),
1993 ((uint32_t)(ts % 1000000)) * 1000);
1995 used_buffer_length -= 24 + GINT32_FROM_BE(*captured_length);
1996 if (used_buffer_length < 0) {
1997 ws_warning("Internal Negative used buffer length.");
1998 closesocket(sock);
1999 return EXIT_CODE_GENERIC;
2002 if (used_buffer_length > 0)
2003 memmove(packet + sizeof(own_pcap_bluetooth_h4_header), payload + GINT32_FROM_BE(*captured_length), used_buffer_length);
2007 closesocket(sock);
2008 return EXIT_CODE_SUCCESS;
2011 /*----------------------------------------------------------------------------*/
2012 /* Android Logcat Text*/
2013 /*----------------------------------------------------------------------------*/
2016 static int capture_android_logcat_text(char *interface, char *fifo,
2017 const char *adb_server_ip, unsigned short *adb_server_tcp_port,
2018 int logcat_ignore_log_buffer, const char *logcat_custom_parameter) {
2019 struct extcap_dumper extcap_dumper;
2020 static char packet[PACKET_LENGTH];
2021 ssize_t length;
2022 size_t used_buffer_length = 0;
2023 socket_handle_t sock;
2024 const char *protocol_name;
2025 size_t exported_pdu_headers_size = 0;
2026 struct exported_pdu_header exported_pdu_header_protocol_normal;
2027 struct exported_pdu_header *exported_pdu_header_protocol;
2028 struct exported_pdu_header exported_pdu_header_end = {0, 0};
2029 static const char *wireshark_protocol_logcat_text = "logcat_text_threadtime";
2030 const char *adb_logcat_template = "shell:export ANDROID_LOG_TAGS=\"\" ; exec logcat -v threadtime%s%s %s";
2031 char *serial_number = NULL;
2032 int result;
2033 char *pos;
2034 const char *logcat_buffer;
2035 const char *logcat_log_buffer;
2037 extcap_dumper = extcap_dumper_open(fifo, EXTCAP_ENCAP_WIRESHARK_UPPER_PDU);
2039 exported_pdu_header_protocol_normal.tag = GUINT16_TO_BE(EXP_PDU_TAG_DISSECTOR_NAME);
2040 exported_pdu_header_protocol_normal.length = GUINT16_TO_BE(strlen(wireshark_protocol_logcat_text) + 2);
2042 serial_number = get_serial_from_interface(interface);
2043 sock = adb_connect_transport(adb_server_ip, adb_server_tcp_port, serial_number);
2044 if (sock == INVALID_SOCKET)
2045 return EXIT_CODE_INVALID_SOCKET_8;
2047 if (is_specified_interface(interface, INTERFACE_ANDROID_LOGCAT_MAIN) || is_specified_interface(interface, INTERFACE_ANDROID_LOGCAT_TEXT_MAIN))
2048 logcat_buffer = " -b main";
2049 else if (is_specified_interface(interface, INTERFACE_ANDROID_LOGCAT_SYSTEM) || is_specified_interface(interface, INTERFACE_ANDROID_LOGCAT_TEXT_SYSTEM))
2050 logcat_buffer = " -b system";
2051 else if (is_specified_interface(interface, INTERFACE_ANDROID_LOGCAT_RADIO) || is_specified_interface(interface, INTERFACE_ANDROID_LOGCAT_TEXT_RADIO))
2052 logcat_buffer = " -b radio";
2053 else if (is_specified_interface(interface, INTERFACE_ANDROID_LOGCAT_EVENTS) || is_specified_interface(interface, INTERFACE_ANDROID_LOGCAT_TEXT_EVENTS))
2054 logcat_buffer = " -b events";
2055 else if (is_specified_interface(interface, INTERFACE_ANDROID_LOGCAT_TEXT_CRASH))
2056 logcat_buffer = " -b crash";
2057 else {
2058 ws_warning("Unknown interface: <%s>", interface);
2059 closesocket(sock);
2060 return EXIT_CODE_GENERIC;
2063 if (logcat_ignore_log_buffer)
2064 logcat_log_buffer = " -T 1";
2065 else
2066 logcat_log_buffer = "";
2068 if (!logcat_custom_parameter)
2069 logcat_custom_parameter = "";
2071 result = snprintf((char *) packet, PACKET_LENGTH, adb_logcat_template, logcat_buffer, logcat_log_buffer, logcat_custom_parameter);
2072 if (result <= 0 || result > PACKET_LENGTH) {
2073 ws_warning("Error while completing adb packet");
2074 closesocket(sock);
2075 return EXIT_CODE_BAD_SIZE_OF_ASSEMBLED_ADB_PACKET_17;
2078 result = adb_send(sock, packet);
2079 if (result) {
2080 ws_warning("Error while sending command <%s>", packet);
2081 closesocket(sock);
2082 return EXIT_CODE_ERROR_WHILE_SENDING_ADB_PACKET_3;
2085 protocol_name = wireshark_protocol_logcat_text;
2086 exported_pdu_header_protocol = &exported_pdu_header_protocol_normal;
2088 memcpy(packet, exported_pdu_header_protocol, sizeof(struct exported_pdu_header));
2089 exported_pdu_headers_size += sizeof(struct exported_pdu_header);
2091 memcpy(packet + exported_pdu_headers_size, protocol_name, GUINT16_FROM_BE(exported_pdu_header_protocol->length) - 2);
2092 exported_pdu_headers_size += GUINT16_FROM_BE(exported_pdu_header_protocol->length);
2094 packet[exported_pdu_headers_size - 1] = 0;
2095 packet[exported_pdu_headers_size - 2] = 0;
2097 memcpy(packet + exported_pdu_headers_size, &exported_pdu_header_end, sizeof(struct exported_pdu_header));
2098 exported_pdu_headers_size += sizeof(struct exported_pdu_header) + GUINT16_FROM_BE(exported_pdu_header_end.length);
2100 used_buffer_length = 0;
2101 while (endless_loop) {
2102 errno = 0;
2103 length = recv(sock, packet + exported_pdu_headers_size + used_buffer_length, (int)(PACKET_LENGTH - exported_pdu_headers_size - used_buffer_length), 0);
2104 if (errno == EAGAIN
2105 #if EWOULDBLOCK != EAGAIN
2106 || errno == EWOULDBLOCK
2107 #endif
2109 continue;
2111 else if (errno != 0) {
2112 ws_warning("ERROR capture: %s", strerror(errno));
2113 closesocket(sock);
2114 return EXIT_CODE_GENERIC;
2117 if (length <= 0) {
2118 ws_warning("Broken socket connection. Try reconnect.");
2119 closesocket(sock);
2120 return EXIT_CODE_GENERIC;
2123 used_buffer_length += length;
2125 while (used_buffer_length > 0 && (pos = (char *) memchr(packet + exported_pdu_headers_size, '\n', used_buffer_length))) {
2126 int ms;
2127 struct tm* date;
2128 time_t seconds;
2129 time_t secs = 0;
2130 int nsecs = 0;
2131 time_t t;
2133 length = (ssize_t)(pos - packet) + 1;
2135 t = time(NULL);
2136 date = localtime(&t);
2137 if (!date)
2138 continue;
2139 if (6 == sscanf(packet + exported_pdu_headers_size, "%d-%d %d:%d:%d.%d", &date->tm_mon, &date->tm_mday, &date->tm_hour,
2140 &date->tm_min, &date->tm_sec, &ms)) {
2141 date->tm_mon -= 1;
2142 date->tm_isdst = -1;
2143 seconds = mktime(date);
2144 secs = (time_t) seconds;
2145 nsecs = (int) (ms * 1e6);
2148 endless_loop = extcap_dumper_dump(extcap_dumper, fifo, packet,
2149 length,
2150 length,
2151 secs, nsecs);
2153 memmove(packet + exported_pdu_headers_size, packet + length, used_buffer_length + exported_pdu_headers_size - length);
2154 used_buffer_length -= length - exported_pdu_headers_size;
2158 closesocket(sock);
2159 return EXIT_CODE_SUCCESS;
2162 /*----------------------------------------------------------------------------*/
2163 /* Android Logger / Logcat */
2164 /*----------------------------------------------------------------------------*/
2166 static int capture_android_logcat(char *interface, char *fifo,
2167 const char *adb_server_ip, unsigned short *adb_server_tcp_port) {
2168 struct extcap_dumper extcap_dumper;
2169 static char packet[PACKET_LENGTH];
2170 ssize_t length;
2171 size_t used_buffer_length = 0;
2172 socket_handle_t sock;
2173 const char *protocol_name;
2174 size_t exported_pdu_headers_size = 0;
2175 struct exported_pdu_header exported_pdu_header_protocol_events;
2176 struct exported_pdu_header exported_pdu_header_protocol_normal;
2177 struct exported_pdu_header *exported_pdu_header_protocol;
2178 struct exported_pdu_header exported_pdu_header_end = {0, 0};
2179 static const char *wireshark_protocol_logcat = "logcat";
2180 static const char *wireshark_protocol_logcat_events = "logcat_events";
2181 const char *adb_command;
2182 uint16_t *payload_length;
2183 uint16_t *try_header_size;
2184 uint32_t *timestamp_secs;
2185 uint32_t *timestamp_nsecs;
2186 uint16_t header_size;
2187 int result;
2188 char *serial_number = NULL;
2190 extcap_dumper = extcap_dumper_open(fifo, EXTCAP_ENCAP_WIRESHARK_UPPER_PDU);
2192 exported_pdu_header_protocol_events.tag = GUINT16_TO_BE(EXP_PDU_TAG_DISSECTOR_NAME);
2193 exported_pdu_header_protocol_events.length = GUINT16_TO_BE(strlen(wireshark_protocol_logcat_events) + 2);
2195 exported_pdu_header_protocol_normal.tag = GUINT16_TO_BE(EXP_PDU_TAG_DISSECTOR_NAME);
2196 exported_pdu_header_protocol_normal.length = GUINT16_TO_BE(strlen(wireshark_protocol_logcat) + 2);
2198 serial_number = get_serial_from_interface(interface);
2199 sock = adb_connect_transport(adb_server_ip, adb_server_tcp_port, serial_number);
2200 if (sock == INVALID_SOCKET)
2201 return EXIT_CODE_INVALID_SOCKET_9;
2203 adb_command = interface_to_logbuf(interface);
2204 if (!adb_command) {
2205 ws_warning("Unknown interface: <%s>", interface);
2206 closesocket(sock);
2207 return EXIT_CODE_GENERIC;
2210 result = adb_send(sock, adb_command);
2211 if (result) {
2212 ws_warning("Error while sending command <%s>", adb_command);
2213 closesocket(sock);
2214 return EXIT_CODE_ERROR_WHILE_SENDING_ADB_PACKET_4;
2217 if (is_specified_interface(interface, INTERFACE_ANDROID_LOGCAT_EVENTS))
2219 protocol_name = wireshark_protocol_logcat_events;
2220 exported_pdu_header_protocol = &exported_pdu_header_protocol_events;
2221 } else {
2222 protocol_name = wireshark_protocol_logcat;
2223 exported_pdu_header_protocol = &exported_pdu_header_protocol_normal;
2226 memcpy(packet, exported_pdu_header_protocol, sizeof(struct exported_pdu_header));
2227 exported_pdu_headers_size += sizeof(struct exported_pdu_header);
2229 memcpy(packet + exported_pdu_headers_size, protocol_name, GUINT16_FROM_BE(exported_pdu_header_protocol->length) - 2);
2230 exported_pdu_headers_size += GUINT16_FROM_BE(exported_pdu_header_protocol->length);
2232 packet[exported_pdu_headers_size - 1] = 0;
2233 packet[exported_pdu_headers_size - 2] = 0;
2235 memcpy(packet + exported_pdu_headers_size, &exported_pdu_header_end, sizeof(struct exported_pdu_header));
2236 exported_pdu_headers_size += sizeof(struct exported_pdu_header) + GUINT16_FROM_BE(exported_pdu_header_end.length);
2238 SET_DATA(payload_length, value_u16, packet + exported_pdu_headers_size + 0);
2239 SET_DATA(try_header_size, value_u16, packet + exported_pdu_headers_size + 2);
2240 SET_DATA(timestamp_secs, value_u32, packet + exported_pdu_headers_size + 12);
2241 SET_DATA(timestamp_nsecs, value_u32, packet + exported_pdu_headers_size + 16);
2243 while (endless_loop) {
2244 errno = 0;
2245 length = recv(sock, packet + exported_pdu_headers_size + used_buffer_length, (int)(PACKET_LENGTH - exported_pdu_headers_size - used_buffer_length), 0);
2246 if (errno == EAGAIN
2247 #if EWOULDBLOCK != EAGAIN
2248 || errno == EWOULDBLOCK
2249 #endif
2251 continue;
2253 else if (errno != 0) {
2254 ws_warning("ERROR capture: %s", strerror(errno));
2255 closesocket(sock);
2256 return EXIT_CODE_GENERIC;
2259 if (length <= 0) {
2260 while (endless_loop) {
2261 ws_warning("Broken socket connection. Try reconnect.");
2262 used_buffer_length = 0;
2263 closesocket(sock);
2265 sock = adb_connect_transport(adb_server_ip, adb_server_tcp_port, serial_number);
2266 if (sock == INVALID_SOCKET)
2267 return EXIT_CODE_INVALID_SOCKET_10;
2269 result = adb_send(sock, adb_command);
2270 if (result) {
2271 ws_warning("WARNING: Error while sending command <%s>", adb_command);
2272 continue;
2275 break;
2279 used_buffer_length += length + exported_pdu_headers_size;
2281 if (*try_header_size != 24)
2282 header_size = 20;
2283 else
2284 header_size = *try_header_size;
2286 length = (*payload_length) + header_size + (ssize_t)exported_pdu_headers_size;
2288 while (used_buffer_length >= exported_pdu_headers_size + header_size && (size_t)length <= used_buffer_length) {
2289 endless_loop = extcap_dumper_dump(extcap_dumper, fifo, packet,
2290 length,
2291 length,
2292 *timestamp_secs, *timestamp_nsecs);
2294 memmove(packet + exported_pdu_headers_size, packet + length, used_buffer_length - length);
2295 used_buffer_length -= length;
2296 used_buffer_length += exported_pdu_headers_size;
2299 length = (*payload_length) + header_size + (ssize_t)exported_pdu_headers_size;
2301 if (*try_header_size != 24)
2302 header_size = 20;
2303 else
2304 header_size = *try_header_size;
2306 used_buffer_length -= exported_pdu_headers_size;
2309 closesocket(sock);
2311 return EXIT_CODE_SUCCESS;
2315 /*----------------------------------------------------------------------------*/
2316 /* Android Wifi Tcpdump */
2317 /* The Tcpdump sends data in pcap format. So for using the extcap_dumper we */
2318 /* need to unpack the pcap and then send the packet data to the dumper. */
2319 /*----------------------------------------------------------------------------*/
2320 static int capture_android_tcpdump(char *interface, char *fifo,
2321 char *capture_filter, const char *adb_server_ip,
2322 unsigned short *adb_server_tcp_port) {
2323 static const char *const adb_shell_tcpdump_format = "exec:tcpdump -U -n -s 0 -u -i %s -w - %s 2>/dev/null";
2324 static const char *const regex_interface = INTERFACE_ANDROID_TCPDUMP "-(?<iface>.*?)-(?<serial>.*)";
2325 struct extcap_dumper extcap_dumper;
2326 static char data[PACKET_LENGTH];
2327 ssize_t length;
2328 ssize_t used_buffer_length = 0;
2329 ssize_t frame_length=0;
2330 socket_handle_t sock;
2331 int result;
2332 char *iface = NULL;
2333 char *serial_number = NULL;
2334 bool nanosecond_timestamps;
2335 bool swap_byte_order;
2336 pcap_hdr_t *global_header;
2337 pcaprec_hdr_t p_header;
2338 GRegex *regex = NULL;
2339 GError *err = NULL;
2340 GMatchInfo *match = NULL;
2341 char *tcpdump_cmd = NULL;
2342 char *quoted_filter = NULL;
2344 regex = g_regex_new(regex_interface, G_REGEX_RAW, (GRegexMatchFlags)0, &err);
2345 if (!regex) {
2346 ws_warning("Failed to compile regex for tcpdump interface");
2347 return EXIT_CODE_GENERIC;
2350 g_regex_match(regex, interface, (GRegexMatchFlags)0, &match);
2351 if (!g_match_info_matches(match)) {
2352 ws_warning("Failed to determine iface name and serial number");
2353 g_regex_unref(regex);
2354 return EXIT_CODE_GENERIC;
2357 iface = g_match_info_fetch_named(match, "iface");
2358 serial_number = g_match_info_fetch_named(match, "serial");
2359 g_match_info_free(match);
2360 g_regex_unref(regex);
2362 /* First check for the device if it is connected or not */
2363 sock = adb_connect_transport(adb_server_ip, adb_server_tcp_port, serial_number);
2364 g_free(serial_number);
2365 if (sock == INVALID_SOCKET) {
2366 g_free(iface);
2367 return EXIT_CODE_INVALID_SOCKET_11;
2370 quoted_filter = g_shell_quote(capture_filter ? capture_filter : "");
2371 tcpdump_cmd = ws_strdup_printf(adb_shell_tcpdump_format, iface, quoted_filter);
2372 g_free(iface);
2373 g_free(quoted_filter);
2374 result = adb_send(sock, tcpdump_cmd);
2375 g_free(tcpdump_cmd);
2376 if (result) {
2377 ws_warning("Error while setting adb transport");
2378 closesocket(sock);
2379 return EXIT_CODE_GENERIC;
2382 while (used_buffer_length < PCAP_GLOBAL_HEADER_LENGTH) {
2383 errno = 0;
2384 length = recv(sock, data + used_buffer_length, (int)(PCAP_GLOBAL_HEADER_LENGTH - used_buffer_length), 0);
2385 if (errno == EAGAIN
2386 #if EWOULDBLOCK != EAGAIN
2387 || errno == EWOULDBLOCK
2388 #endif
2390 continue;
2392 else if (errno != 0) {
2393 ws_warning("ERROR capture: %s", strerror(errno));
2394 closesocket(sock);
2395 return EXIT_CODE_GENERIC;
2398 if (length <= 0) {
2399 ws_warning("Broken socket connection.");
2400 closesocket(sock);
2401 return EXIT_CODE_GENERIC;
2404 used_buffer_length += length;
2407 global_header = (pcap_hdr_t*) data;
2408 switch (global_header->magic_number) {
2409 case 0xa1b2c3d4:
2410 swap_byte_order = false;
2411 nanosecond_timestamps = false;
2412 break;
2413 case 0xd4c3b2a1:
2414 swap_byte_order = true;
2415 nanosecond_timestamps = false;
2416 break;
2417 case 0xa1b23c4d:
2418 swap_byte_order = false;
2419 nanosecond_timestamps = true;
2420 break;
2421 case 0x4d3cb2a1:
2422 swap_byte_order = true;
2423 nanosecond_timestamps = true;
2424 break;
2425 default:
2426 ws_warning("Received incorrect magic");
2427 closesocket(sock);
2428 return EXIT_CODE_GENERIC;
2430 int encap = (int)(swap_byte_order ? GUINT32_SWAP_LE_BE(global_header->network) : global_header->network);
2431 #ifndef ANDROIDDUMP_USE_LIBPCAP
2432 encap = wtap_pcap_encap_to_wtap_encap(encap);
2433 #endif
2434 extcap_dumper = extcap_dumper_open(fifo, encap);
2436 used_buffer_length = 0;
2437 while (endless_loop) {
2438 ssize_t offset = 0;
2440 errno = 0;
2441 length = recv(sock, data + used_buffer_length, (int)(PACKET_LENGTH - used_buffer_length), 0);
2442 if (errno == EAGAIN
2443 #if EWOULDBLOCK != EAGAIN
2444 || errno == EWOULDBLOCK
2445 #endif
2447 continue;
2449 else if (errno != 0) {
2450 ws_warning("ERROR capture: %s", strerror(errno));
2451 closesocket(sock);
2452 return EXIT_CODE_GENERIC;
2455 if (length <= 0) {
2456 ws_warning("Broken socket connection.");
2457 closesocket(sock);
2458 return EXIT_CODE_GENERIC;
2461 used_buffer_length += length;
2463 while ((used_buffer_length - offset) > PCAP_RECORD_HEADER_LENGTH) {
2464 p_header = *((pcaprec_hdr_t*) (data + offset));
2465 if (swap_byte_order) {
2466 p_header.ts_sec = GUINT32_SWAP_LE_BE(p_header.ts_sec);
2467 p_header.ts_usec = GUINT32_SWAP_LE_BE(p_header.ts_usec);
2468 p_header.incl_len = GUINT32_SWAP_LE_BE(p_header.incl_len);
2469 p_header.orig_len = GUINT32_SWAP_LE_BE(p_header.orig_len);
2471 if (!nanosecond_timestamps) {
2472 p_header.ts_usec = p_header.ts_usec * 1000;
2475 frame_length = p_header.incl_len + PCAP_RECORD_HEADER_LENGTH;
2476 if ((used_buffer_length - offset) < frame_length) {
2477 break; /* wait for complete packet */
2480 /* It was observed that some times tcpdump reports the length of packet as '0' and that leads to the
2481 * ( Warn Error "Less data was read than was expected" while reading )
2482 * So to avoid this error we are checking for length of packet before passing it to dumper.
2484 if (p_header.incl_len > 0) {
2485 endless_loop = extcap_dumper_dump(extcap_dumper, fifo, data + offset + PCAP_RECORD_HEADER_LENGTH,
2486 p_header.incl_len, p_header.orig_len, p_header.ts_sec, p_header.ts_usec);
2489 offset += frame_length;
2492 if (offset < used_buffer_length) {
2493 memmove(data, data + offset, used_buffer_length - offset);
2495 used_buffer_length -= offset;
2498 closesocket(sock);
2499 return EXIT_CODE_SUCCESS;
2502 int main(int argc, char *argv[]) {
2503 char *err_msg;
2504 int ret = EXIT_CODE_GENERIC;
2505 int option_idx = 0;
2506 int result;
2507 const char *adb_server_ip = NULL;
2508 unsigned short *adb_server_tcp_port = NULL;
2509 unsigned int logcat_text = 0;
2510 unsigned int logcat_ignore_log_buffer = 0;
2511 const char *logcat_custom_parameter = NULL;
2512 const char *default_adb_server_ip = "127.0.0.1";
2513 unsigned short default_adb_server_tcp_port = 5037;
2514 unsigned short local_adb_server_tcp_port;
2515 unsigned short local_bt_server_tcp_port;
2516 unsigned short local_bt_local_tcp_port;
2517 unsigned short *bt_server_tcp_port = NULL;
2518 unsigned int bt_forward_socket = 0;
2519 const char *bt_local_ip = NULL;
2520 unsigned short *bt_local_tcp_port = NULL;
2521 unsigned short default_bt_server_tcp_port = 4330;
2522 const char *default_bt_local_ip = "127.0.0.1";
2523 unsigned short default_bt_local_tcp_port = 4330;
2524 extcap_parameters * extcap_conf = NULL;
2525 char *help_url;
2526 char *help_header = NULL;
2528 cmdarg_err_init(androiddump_cmdarg_err, androiddump_cmdarg_err);
2530 /* Initialize log handler early so we can have proper logging during startup. */
2531 extcap_log_init("androiddump");
2534 * Get credential information for later use.
2536 init_process_policies();
2539 * Attempt to get the pathname of the directory containing the
2540 * executable file.
2542 err_msg = configuration_init(argv[0], NULL);
2543 if (err_msg != NULL) {
2544 ws_warning("Can't get pathname of directory containing the extcap program: %s.",
2545 err_msg);
2546 g_free(err_msg);
2549 init_report_failure_message("androiddump");
2551 extcap_conf = g_new0(extcap_parameters, 1);
2553 help_url = data_file_url("androiddump.html");
2554 extcap_base_set_util_info(extcap_conf, argv[0], ANDROIDDUMP_VERSION_MAJOR, ANDROIDDUMP_VERSION_MINOR,
2555 ANDROIDDUMP_VERSION_RELEASE, help_url);
2556 g_free(help_url);
2558 help_header = ws_strdup_printf(
2559 " %s --extcap-interfaces [--adb-server-ip=<arg>] [--adb-server-tcp-port=<arg>]\n"
2560 " %s --extcap-interface=INTERFACE --extcap-dlts\n"
2561 " %s --extcap-interface=INTERFACE --extcap-config\n"
2562 " %s --extcap-interface=INTERFACE --fifo=PATH_FILENAME --capture\n"
2563 "\nINTERFACE has the form TYPE-DEVICEID:\n"
2564 "\t""For example: "INTERFACE_ANDROID_BLUETOOTH_BTSNOOP_NET"-W3D7N15C29005648""\n"
2565 "\n"
2566 "\tTYPE is one of:\n"
2567 "\t"INTERFACE_ANDROID_LOGCAT_MAIN"\n"
2568 "\t"INTERFACE_ANDROID_LOGCAT_SYSTEM"\n"
2569 "\t"INTERFACE_ANDROID_LOGCAT_RADIO"\n"
2570 "\t"INTERFACE_ANDROID_LOGCAT_EVENTS"\n"
2571 "\t"INTERFACE_ANDROID_LOGCAT_TEXT_MAIN"\n"
2572 "\t"INTERFACE_ANDROID_LOGCAT_TEXT_SYSTEM"\n"
2573 "\t"INTERFACE_ANDROID_LOGCAT_TEXT_RADIO"\n"
2574 "\t"INTERFACE_ANDROID_LOGCAT_TEXT_EVENTS"\n"
2575 "\t"INTERFACE_ANDROID_LOGCAT_TEXT_CRASH"\n"
2576 "\t"INTERFACE_ANDROID_BLUETOOTH_HCIDUMP"\n"
2577 "\t"INTERFACE_ANDROID_BLUETOOTH_EXTERNAL_PARSER"\n"
2578 "\t"INTERFACE_ANDROID_BLUETOOTH_BTSNOOP_NET"\n"
2579 "\t"INTERFACE_ANDROID_TCPDUMP"\n"
2580 "\n"
2581 "\t""DEVICEID is the identifier of the device provided by Android SDK (see \"adb devices\")\n"
2582 "\t""For example: W3D7N15C29005648""\n",
2584 argv[0], argv[0], argv[0], argv[0]);
2585 extcap_help_add_header(extcap_conf, help_header);
2586 g_free(help_header);
2588 extcap_help_add_option(extcap_conf, "--help", "print this help");
2589 extcap_help_add_option(extcap_conf, "--adb-server-ip <IP>", "the IP address of the ADB server");
2590 extcap_help_add_option(extcap_conf, "--adb-server-tcp-port <port>", "the TCP port of the ADB server");
2591 extcap_help_add_option(extcap_conf, "--logcat-text", "use logcat text format");
2592 extcap_help_add_option(extcap_conf, "--logcat-ignore-log-buffer", "ignore log buffer");
2593 extcap_help_add_option(extcap_conf, "--logcat-custom-options <text>", "use custom logcat parameters");
2594 extcap_help_add_option(extcap_conf, "--bt-server-tcp-port <port>", "bluetooth server TCP port");
2595 extcap_help_add_option(extcap_conf, "--bt-forward-socket <path>", "bluetooth forward socket");
2596 extcap_help_add_option(extcap_conf, "--bt-local-ip <IP>", "the bluetooth local IP");
2597 extcap_help_add_option(extcap_conf, "--bt-local-tcp-port <port>", "the bluetooth local TCP port");
2599 ws_opterr = 0;
2600 ws_optind = 0;
2602 if (argc == 1) {
2603 extcap_help_print(extcap_conf);
2604 ret = EXIT_CODE_SUCCESS;
2605 goto end;
2608 while ((result = ws_getopt_long(argc, argv, "", longopts, &option_idx)) != -1) {
2609 switch (result) {
2611 case OPT_VERSION:
2612 extcap_version_print(extcap_conf);
2613 ret = EXIT_CODE_SUCCESS;
2614 goto end;
2615 case OPT_HELP:
2616 extcap_help_print(extcap_conf);
2617 ret = EXIT_CODE_SUCCESS;
2618 goto end;
2619 case OPT_CONFIG_ADB_SERVER_IP:
2620 adb_server_ip = ws_optarg;
2621 break;
2622 case OPT_CONFIG_ADB_SERVER_TCP_PORT:
2623 adb_server_tcp_port = &local_adb_server_tcp_port;
2624 if (!ws_optarg){
2625 ws_warning("Impossible exception. Parameter required argument, but there is no it right now.");
2626 goto end;
2628 if (!ws_strtou16(ws_optarg, NULL, adb_server_tcp_port)) {
2629 ws_warning("Invalid adb server TCP port: %s", ws_optarg);
2630 goto end;
2632 break;
2633 case OPT_CONFIG_LOGCAT_TEXT:
2634 if (ws_optarg && !*ws_optarg)
2635 logcat_text = true;
2636 else
2637 logcat_text = (g_ascii_strncasecmp(ws_optarg, "true", 4) == 0);
2638 break;
2639 case OPT_CONFIG_LOGCAT_IGNORE_LOG_BUFFER:
2640 if (ws_optarg == NULL || (ws_optarg && !*ws_optarg))
2641 logcat_ignore_log_buffer = true;
2642 else
2643 logcat_ignore_log_buffer = (g_ascii_strncasecmp(ws_optarg, "true", 4) == 0);
2644 break;
2645 case OPT_CONFIG_LOGCAT_CUSTOM_OPTIONS:
2646 if (ws_optarg == NULL || (ws_optarg && *ws_optarg == '\0')) {
2647 logcat_custom_parameter = NULL;
2648 break;
2651 if (g_regex_match_simple("(^|\\s)-[bBcDfgLnpPrv]", ws_optarg, G_REGEX_RAW, (GRegexMatchFlags)0)) {
2652 ws_error("Found prohibited option in logcat-custom-options");
2653 return EXIT_CODE_GENERIC;
2656 logcat_custom_parameter = ws_optarg;
2658 break;
2659 case OPT_CONFIG_BT_SERVER_TCP_PORT:
2660 bt_server_tcp_port = &local_bt_server_tcp_port;
2661 if (!ws_optarg){
2662 ws_warning("Impossible exception. Parameter required argument, but there is no it right now.");
2663 goto end;
2665 if (!ws_strtou16(ws_optarg, NULL, bt_server_tcp_port)) {
2666 ws_warning("Invalid bluetooth server TCP port: %s", ws_optarg);
2667 goto end;
2669 break;
2670 case OPT_CONFIG_BT_FORWARD_SOCKET:
2671 bt_forward_socket = (g_ascii_strncasecmp(ws_optarg, "true", 4) == 0);
2672 break;
2673 case OPT_CONFIG_BT_LOCAL_IP:
2674 bt_local_ip = ws_optarg;
2675 break;
2676 case OPT_CONFIG_BT_LOCAL_TCP_PORT:
2677 bt_local_tcp_port = &local_bt_local_tcp_port;
2678 if (!ws_optarg){
2679 ws_warning("Impossible exception. Parameter required argument, but there is no it right now.");
2680 goto end;
2682 if (!ws_strtou16(ws_optarg, NULL, bt_local_tcp_port)) {
2683 ws_warning("Invalid bluetooth local tcp port: %s", ws_optarg);
2684 goto end;
2686 break;
2687 default:
2688 if (!extcap_base_parse_options(extcap_conf, result - EXTCAP_OPT_LIST_INTERFACES, ws_optarg))
2690 ws_warning("Invalid argument <%s>. Try --help.\n", argv[ws_optind - 1]);
2691 goto end;
2696 if (!adb_server_ip)
2697 adb_server_ip = default_adb_server_ip;
2699 if (!adb_server_tcp_port)
2700 adb_server_tcp_port = &default_adb_server_tcp_port;
2702 if (!bt_server_tcp_port)
2703 bt_server_tcp_port = &default_bt_server_tcp_port;
2705 if (!bt_local_ip)
2706 bt_local_ip = default_bt_local_ip;
2708 if (!bt_local_tcp_port)
2709 bt_local_tcp_port = &default_bt_local_tcp_port;
2711 err_msg = ws_init_sockets();
2712 if (err_msg != NULL) {
2713 ws_warning("ERROR: %s", err_msg);
2714 g_free(err_msg);
2715 ws_warning("%s", please_report_bug());
2716 goto end;
2719 extcap_cmdline_debug(argv, argc);
2721 if (extcap_conf->do_list_interfaces)
2722 register_interfaces(extcap_conf, adb_server_ip, adb_server_tcp_port);
2724 /* NOTE:
2725 * extcap implementation calls androiddump --extcap-dlts for each interface.
2726 * The only way to know whether an interface exists or not is to go through the
2727 * whole process of listing all interfaces (i.e. calling register_interfaces
2728 * function). Since being a system resource heavy operation and repeated for
2729 * each interface instead register a fake interface to be returned for dlt
2730 * listing only purpose
2732 if (extcap_conf->do_list_dlts) {
2733 new_fake_interface_for_list_dlts(extcap_conf, extcap_conf->interface);
2736 if (extcap_base_handle_interface(extcap_conf)) {
2737 ret = EXIT_CODE_SUCCESS;
2738 goto end;
2741 if (extcap_conf->show_config) {
2742 ret = list_config(extcap_conf->interface);
2743 goto end;
2746 if (extcap_conf->capture) {
2747 if (extcap_conf->interface && is_logcat_interface(extcap_conf->interface))
2748 if (logcat_text)
2749 ret = capture_android_logcat_text(extcap_conf->interface,
2750 extcap_conf->fifo, adb_server_ip, adb_server_tcp_port,
2751 logcat_ignore_log_buffer, logcat_custom_parameter);
2752 else
2753 ret = capture_android_logcat(extcap_conf->interface,
2754 extcap_conf->fifo, adb_server_ip, adb_server_tcp_port);
2755 else if (extcap_conf->interface && is_logcat_text_interface(extcap_conf->interface))
2756 ret = capture_android_logcat_text(extcap_conf->interface,
2757 extcap_conf->fifo, adb_server_ip, adb_server_tcp_port,
2758 logcat_ignore_log_buffer, logcat_custom_parameter);
2759 else if (extcap_conf->interface && is_specified_interface(extcap_conf->interface, INTERFACE_ANDROID_BLUETOOTH_HCIDUMP))
2760 ret = capture_android_bluetooth_hcidump(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_BLUETOOTH_EXTERNAL_PARSER))
2762 ret = capture_android_bluetooth_external_parser(extcap_conf->interface, extcap_conf->fifo, adb_server_ip, adb_server_tcp_port,
2763 bt_server_tcp_port, bt_forward_socket, bt_local_ip, bt_local_tcp_port);
2764 else if (extcap_conf->interface && (is_specified_interface(extcap_conf->interface, INTERFACE_ANDROID_BLUETOOTH_BTSNOOP_NET)))
2765 ret = capture_android_bluetooth_btsnoop_net(extcap_conf->interface, extcap_conf->fifo, adb_server_ip, adb_server_tcp_port);
2766 else if (extcap_conf->interface && (is_specified_interface(extcap_conf->interface,INTERFACE_ANDROID_TCPDUMP)))
2767 ret = capture_android_tcpdump(extcap_conf->interface, extcap_conf->fifo, extcap_conf->capture_filter, adb_server_ip, adb_server_tcp_port);
2769 goto end;
2772 /* no action was given, assume success */
2773 ret = EXIT_CODE_SUCCESS;
2775 end:
2776 /* clean up stuff */
2777 extcap_base_cleanup(&extcap_conf);
2778 #ifndef ANDROIDDUMP_USE_LIBPCAP
2779 wtap_cleanup();
2780 #endif
2782 return ret;
2786 * Editor modelines - https://www.wireshark.org/tools/modelines.html
2788 * Local variables:
2789 * c-basic-offset: 4
2790 * tab-width: 8
2791 * indent-tabs-mode: nil
2792 * End:
2794 * vi: set shiftwidth=4 tabstop=8 expandtab:
2795 * :indentSize=4:tabSize=8:noTabs=true: