TODO epan/dissectors/asn1/kerberos/packet-kerberos-template.c new GSS flags
[wireshark-sm.git] / extcap / androiddump.c
blob6796195a24ecfb81cd4591cb51ee30f089c999f6
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;
356 static void useSndTimeout(socket_handle_t sock) {
357 int res;
358 #ifdef _WIN32
359 const DWORD socket_timeout = SOCKET_RW_TIMEOUT_MS;
361 res = setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, (const char *) &socket_timeout, (socklen_t)sizeof(socket_timeout));
362 #else
363 const struct timeval socket_timeout = {
364 .tv_sec = SOCKET_RW_TIMEOUT_MS / 1000,
365 .tv_usec = (SOCKET_RW_TIMEOUT_MS % 1000) * 1000
368 res = setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, &socket_timeout, (socklen_t)sizeof(socket_timeout));
369 #endif
370 if (res != 0)
371 ws_debug("Can't set socket timeout, using default");
374 static void useNonBlockingConnectTimeout(socket_handle_t sock) {
375 #ifdef _WIN32
376 unsigned long non_blocking = 1;
378 /* set socket to non-blocking */
379 ioctlsocket(sock, FIONBIO, &non_blocking);
380 #else
381 int flags = fcntl(sock, F_GETFL);
382 fcntl(sock, F_SETFL, flags | O_NONBLOCK);
383 #endif
386 static void useNormalConnectTimeout(socket_handle_t sock) {
387 int res_snd;
388 int res_rcv;
389 #ifdef _WIN32
390 const DWORD socket_timeout = SOCKET_RW_TIMEOUT_MS;
391 unsigned long non_blocking = 0;
393 res_snd = setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, (const char *) &socket_timeout, sizeof(socket_timeout));
394 res_rcv = setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (const char *) &socket_timeout, sizeof(socket_timeout));
395 ioctlsocket(sock, FIONBIO, &non_blocking);
396 #else
397 int flags = fcntl(sock, F_GETFL);
398 fcntl(sock, F_SETFL, flags & ~O_NONBLOCK);
399 const struct timeval socket_timeout = {
400 .tv_sec = SOCKET_RW_TIMEOUT_MS / 1000,
401 .tv_usec = (SOCKET_RW_TIMEOUT_MS % 1000) * 1000
404 res_snd = setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, &socket_timeout, sizeof(socket_timeout));
405 res_rcv = setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &socket_timeout, sizeof(socket_timeout));
406 #endif
407 if (res_snd != 0)
408 ws_debug("Can't set socket timeout, using default");
409 if (res_rcv != 0)
410 ws_debug("Can't set socket timeout, using default");
413 static struct extcap_dumper extcap_dumper_open(char *fifo, int encap) {
414 struct extcap_dumper extcap_dumper;
416 #ifdef ANDROIDDUMP_USE_LIBPCAP
417 pcap_t *pcap;
419 pcap = pcap_open_dead_with_tstamp_precision(encap, PACKET_LENGTH, PCAP_TSTAMP_PRECISION_NANO);
420 extcap_dumper.dumper.pcap = pcap_dump_open(pcap, fifo);
421 if (!extcap_dumper.dumper.pcap) {
422 ws_warning("Can't open %s for saving packets: %s", fifo, pcap_geterr(pcap));
423 pcap_close(pcap);
424 exit(EXIT_CODE_CANNOT_SAVE_LIBPCAP_DUMP);
426 extcap_dumper.encap = encap;
427 if (pcap_dump_flush(extcap_dumper.dumper.pcap) == -1) {
428 ws_warning("Write to %s failed: %s", fifo, g_strerror(errno));
430 #else
431 wtap_dump_params params = WTAP_DUMP_PARAMS_INIT;
432 int file_type_subtype;
433 int err = 0;
434 char *err_info = NULL;
436 wtap_init(false);
438 params.encap = encap;
439 params.snaplen = PACKET_LENGTH;
440 file_type_subtype = wtap_pcap_nsec_file_type_subtype();
441 extcap_dumper.dumper.wtap = wtap_dump_open(fifo, file_type_subtype, WTAP_UNCOMPRESSED, &params, &err, &err_info);
442 if (!extcap_dumper.dumper.wtap) {
443 cfile_dump_open_failure_message(fifo, err, err_info, file_type_subtype);
444 exit(EXIT_CODE_CANNOT_SAVE_WIRETAP_DUMP);
446 extcap_dumper.encap = encap;
447 if (!wtap_dump_flush(extcap_dumper.dumper.wtap, &err)) {
448 cfile_dump_open_failure_message(fifo, err, NULL, file_type_subtype);
449 exit(EXIT_CODE_CANNOT_SAVE_WIRETAP_DUMP);
451 #endif
453 return extcap_dumper;
456 static bool extcap_dumper_dump(struct extcap_dumper extcap_dumper,
457 char *fifo, char *buffer,
458 ssize_t captured_length, ssize_t reported_length,
459 time_t seconds, int nanoseconds) {
460 #ifdef ANDROIDDUMP_USE_LIBPCAP
461 struct pcap_pkthdr pcap_header;
463 pcap_header.caplen = (bpf_u_int32) captured_length;
464 pcap_header.len = (bpf_u_int32) reported_length;
465 pcap_header.ts.tv_sec = seconds;
466 pcap_header.ts.tv_usec = nanoseconds / 1000;
468 pcap_dump((u_char *) extcap_dumper.dumper.pcap, &pcap_header, buffer);
469 if (pcap_dump_flush(extcap_dumper.dumper.pcap) == -1) {
470 ws_warning("Write to %s failed: %s", fifo, g_strerror(errno));
472 #else
473 int err = 0;
474 char *err_info;
475 wtap_rec rec;
477 rec.rec_type = REC_TYPE_PACKET;
478 rec.presence_flags = WTAP_HAS_TS;
479 rec.rec_header.packet_header.caplen = (uint32_t) captured_length;
480 rec.rec_header.packet_header.len = (uint32_t) reported_length;
482 rec.ts.secs = seconds;
483 rec.ts.nsecs = (int) nanoseconds;
485 rec.block = NULL;
487 /* NOTE: Try to handle pseudoheaders manually */
488 if (extcap_dumper.encap == EXTCAP_ENCAP_BLUETOOTH_H4_WITH_PHDR) {
489 uint32_t *direction;
491 SET_DATA(direction, value_u32, buffer)
493 rec.rec_header.packet_header.pseudo_header.bthci.sent = GINT32_FROM_BE(*direction) ? 0 : 1;
495 rec.rec_header.packet_header.len -= (uint32_t)sizeof(own_pcap_bluetooth_h4_header);
496 rec.rec_header.packet_header.caplen -= (uint32_t)sizeof(own_pcap_bluetooth_h4_header);
498 buffer += sizeof(own_pcap_bluetooth_h4_header);
500 rec.rec_header.packet_header.pkt_encap = extcap_dumper.encap;
502 if (!wtap_dump(extcap_dumper.dumper.wtap, &rec, (const uint8_t *) buffer, &err, &err_info)) {
503 cfile_write_failure_message(NULL, fifo, err, err_info, 0,
504 wtap_dump_file_type_subtype(extcap_dumper.dumper.wtap));
505 return false;
508 if (!wtap_dump_flush(extcap_dumper.dumper.wtap, &err)) {
509 cfile_write_failure_message(NULL, fifo, err, NULL, 0,
510 wtap_dump_file_type_subtype(extcap_dumper.dumper.wtap));
511 return false;
513 #endif
515 return true;
519 static socket_handle_t adb_connect(const char *server_ip, unsigned short *server_tcp_port) {
520 socket_handle_t sock;
521 socklen_t length;
522 struct sockaddr_in server;
523 struct sockaddr_in client;
524 int status;
525 #ifndef _WIN32
526 int result;
527 #endif
528 int tries = 0;
530 memset(&server, 0x0, sizeof(server));
532 server.sin_family = AF_INET;
533 server.sin_port = GINT16_TO_BE(*server_tcp_port);
534 ws_inet_pton4(server_ip, (ws_in4_addr *)&(server.sin_addr.s_addr));
536 if ((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET) {
537 ws_warning("Cannot open system TCP socket: %s", strerror(errno));
538 return INVALID_SOCKET;
541 useNonBlockingConnectTimeout(sock);
542 status = connect(sock, (struct sockaddr *) &server, (socklen_t)sizeof(server));
543 #ifdef _WIN32
544 if ((status == SOCKET_ERROR) && (WSAGetLastError() == WSAEWOULDBLOCK)) {
545 #else
546 if ((status == SOCKET_ERROR) && (errno == EINPROGRESS)) {
547 #endif
548 while (tries < SOCKET_CONNECT_TIMEOUT_TRIES) {
549 tries += 1;
550 struct timeval timeout = {
551 .tv_sec = 0,
552 .tv_usec = SOCKET_CONNECT_DELAY_US,
554 fd_set fdset;
555 FD_ZERO(&fdset);
556 FD_SET(sock, &fdset);
557 #ifdef _WIN32
558 if ((select(0, NULL, &fdset, NULL, &timeout) != 0) && (FD_ISSET(sock, &fdset))) {
559 status = 0;
560 break;
561 #else
562 if ((select(sock+1, NULL, &fdset, NULL, &timeout) != 0) && (FD_ISSET(sock, &fdset))) {
563 length = sizeof(result);
564 getsockopt(sock, SOL_SOCKET, SO_ERROR, &result, &length);
565 if (result == 0) {
566 status = 0;
567 } else {
568 ws_debug("Error connecting to ADB: <%s>", strerror(result));
570 break;
571 #endif
572 } else {
573 ws_debug("Try %i: Timeout connecting to ADB", tries);
577 useNormalConnectTimeout(sock);
579 if (status == SOCKET_ERROR) {
580 #if 0
581 /* NOTE: This does not work well - make significant delay while initializing Wireshark.
582 Do fork() then call "adb" also does not make sense, because there is need to
583 do something like sleep(1) to ensure adb is started... system() cannot be used
584 on Windows, because open console window. This helper does not work as expected,
585 so disable it and user must ensure that adb is started (adb start-server,
586 but also all other command start-server automatically)
588 #ifdef _WIN32
589 if (_execlp("adb", "adb", "start-server", NULL)) {
590 #else
591 if (execlp("adb", "adb", "start-server", NULL)) {
592 #endif
593 errmsg("WARNING: Cannot execute system command to start adb: %s", strerror(errno));
594 closesocket(sock);
595 return INVALID_SOCKET;
598 if (connect(sock, (struct sockaddr *) &server, (socklen_t)sizeof(server)) == SOCKET_ERROR) {
599 ws_warning("Cannot connect to ADB: <%s> Please check that adb daemon is running.", strerror(errno));
600 closesocket(sock);
601 return INVALID_SOCKET;
603 #else
604 ws_debug("Cannot connect to ADB: Please check that adb daemon is running.");
605 closesocket(sock);
606 return INVALID_SOCKET;
607 #endif
610 length = sizeof(client);
611 if (getsockname(sock, (struct sockaddr *) &client, &length)) {
612 ws_warning("getsockname: %s", strerror(errno));
613 closesocket(sock);
614 return INVALID_SOCKET;
617 if (length != sizeof(client)) {
618 ws_warning("incorrect length");
619 closesocket(sock);
620 return INVALID_SOCKET;
623 ws_debug("Client port %u", GUINT16_FROM_BE(client.sin_port));
625 return sock;
629 static char *adb_send_and_receive(socket_handle_t sock, const char *adb_service,
630 char *buffer, size_t buffer_length, size_t *data_length) {
631 size_t used_buffer_length;
632 size_t bytes_to_read;
633 uint32_t length;
634 ssize_t result;
635 char status[4];
636 char tmp_buffer;
637 size_t adb_service_length;
639 adb_service_length = strlen(adb_service);
640 if (adb_service_length > INT_MAX) {
641 ws_warning("Service name too long when sending <%s> to ADB daemon", adb_service);
642 if (data_length)
643 *data_length = 0;
644 return NULL;
647 /* 8 bytes of hex length + terminating NUL */
648 if (buffer_length < 9) {
649 ws_warning("Buffer for response too short while sending <%s> to ADB daemon", adb_service);
650 if (data_length)
651 *data_length = 0;
652 return NULL;
655 snprintf(buffer, buffer_length, ADB_HEX4_FORMAT, adb_service_length);
656 result = send(sock, buffer, ADB_HEX4_LEN, 0);
657 if (result < ADB_HEX4_LEN) {
658 ws_warning("Error while sending <%s> length to ADB daemon", adb_service);
659 return NULL;
662 result = send(sock, adb_service, (int) adb_service_length, 0);
663 if (result != (ssize_t) adb_service_length) {
664 ws_warning("Error while sending <%s> to ADB daemon", adb_service);
665 if (data_length)
666 *data_length = 0;
667 return NULL;
670 used_buffer_length = 0;
671 while (used_buffer_length < 8) {
672 bytes_to_read = buffer_length - used_buffer_length;
673 if (bytes_to_read > INT_MAX)
674 bytes_to_read = INT_MAX;
675 result = recv(sock, buffer + used_buffer_length, (int)bytes_to_read, 0);
677 if (result <= 0) {
678 ws_warning("Broken socket connection while fetching reply status for <%s>", adb_service);
679 if (data_length)
680 *data_length = 0;
681 return NULL;
684 used_buffer_length += result;
687 memcpy(status, buffer, 4);
688 tmp_buffer = buffer[8];
689 buffer[8] = '\0';
690 if (!ws_hexstrtou32(buffer + 4, NULL, &length)) {
691 ws_warning("Invalid reply length <%s> while reading reply for <%s>", buffer + 4, adb_service);
692 if (data_length)
693 *data_length = 0;
694 return NULL;
696 buffer[8] = tmp_buffer;
698 if (buffer_length < length + 8) {
699 ws_warning("Buffer for response too short while sending <%s> to ADB daemon", adb_service);
700 if (data_length)
701 *data_length = 0;
702 return NULL;
705 while (used_buffer_length < length + 8) {
706 bytes_to_read = buffer_length - used_buffer_length;
707 if (bytes_to_read > INT_MAX)
708 bytes_to_read = INT_MAX;
709 result = recv(sock, buffer + used_buffer_length, (int)bytes_to_read, 0);
711 if (result <= 0) {
712 ws_warning("Broken socket connection while reading reply for <%s>", adb_service);
713 if (data_length)
714 *data_length = 0;
715 return NULL;
718 used_buffer_length += result;
721 if (data_length)
722 *data_length = used_buffer_length - 8;
724 if (memcmp(status, "OKAY", 4)) {
725 ws_warning("Error while receiving by ADB for <%s>", adb_service);
726 if (data_length)
727 *data_length = 0;
728 return NULL;
731 return buffer + 8;
735 static char *adb_send_and_read(socket_handle_t sock, const char *adb_service, char *buffer,
736 int buffer_length, ssize_t *data_length) {
737 ssize_t used_buffer_length;
738 ssize_t result;
739 char status[4];
740 size_t adb_service_length;
742 adb_service_length = strlen(adb_service);
743 snprintf(buffer, buffer_length, ADB_HEX4_FORMAT, adb_service_length);
745 result = send(sock, buffer, ADB_HEX4_LEN, 0);
746 if (result < ADB_HEX4_LEN) {
747 ws_warning("Error while sending <%s> to ADB daemon", adb_service);
748 return NULL;
751 result = send(sock, adb_service, (int) adb_service_length, 0);
752 if (result != (ssize_t) adb_service_length) {
753 ws_warning("Error while sending <%s> to ADB", adb_service);
754 if (data_length)
755 *data_length = 0;
756 return NULL;
759 used_buffer_length = 0;
760 while (used_buffer_length < 4) {
761 result = recv(sock, buffer + used_buffer_length, (int)(buffer_length - used_buffer_length), 0);
763 if (result <= 0) {
764 ws_warning("Broken socket connection while fetching reply status for <%s>", adb_service);
766 return NULL;
769 used_buffer_length += result;
772 memcpy(status, buffer, 4);
774 while (result > 0) {
775 result= recv(sock, buffer + used_buffer_length, (int)(buffer_length - used_buffer_length), 0);
777 if (result < 0) {
778 ws_warning("Broken socket connection while reading reply for <%s>", adb_service);
780 return NULL;
781 } else if (result == 0) {
782 break;
785 used_buffer_length += result;
788 if (data_length)
789 *data_length = used_buffer_length - 4;
791 if (memcmp(status, "OKAY", 4)) {
792 ws_warning("Error while receiving by ADB for <%s>", adb_service);
793 if (data_length)
794 *data_length = 0;
795 return NULL;
798 return buffer + 4;
802 static int adb_send(socket_handle_t sock, const char *adb_service) {
803 char buffer[5];
804 int used_buffer_length;
805 ssize_t result;
806 size_t adb_service_length;
808 adb_service_length = strlen(adb_service);
809 result = snprintf(buffer, sizeof(buffer), ADB_HEX4_FORMAT, adb_service_length);
810 if ((size_t)result >= sizeof(buffer)) {
811 /* Truncation (or failure somehow) */
812 ws_warning("Service name too long when sending <%s> to ADB daemon", adb_service);
813 return EXIT_CODE_ERROR_WHILE_SENDING_ADB_PACKET_1;
816 result = send(sock, buffer, ADB_HEX4_LEN, 0);
817 if (result < ADB_HEX4_LEN) {
818 ws_warning("Error while sending <%s> to ADB daemon", adb_service);
819 return EXIT_CODE_ERROR_WHILE_SENDING_ADB_PACKET_1;
822 result = send(sock, adb_service, (int) adb_service_length, 0);
823 if (result != (ssize_t) adb_service_length) {
824 ws_warning("Error while sending <%s> to ADB", adb_service);
825 return EXIT_CODE_ERROR_WHILE_SENDING_ADB_PACKET_1;
828 used_buffer_length = 0;
829 while (used_buffer_length < 4) {
830 result = recv(sock, buffer + used_buffer_length, 4 - used_buffer_length, 0);
832 if (result <= 0) {
833 ws_warning("Broken socket connection while fetching reply status for <%s>", adb_service);
835 return EXIT_CODE_ERROR_WHILE_RECEIVING_ADB_PACKET_STATUS;
838 used_buffer_length += (int)result;
841 if (memcmp(buffer, "OKAY", 4)) {
842 ws_debug("Error while receiving by ADB for <%s>", adb_service);
844 return EXIT_CODE_ERROR_WHILE_RECEIVING_ADB_PACKET_DATA;
847 return EXIT_CODE_SUCCESS;
851 static socket_handle_t
852 adb_connect_transport(const char *server_ip, unsigned short *server_tcp_port,
853 const char* serial_number)
855 static const char *const adb_transport_serial_templace = "host:transport:%s";
856 static const char *const adb_transport_any = "host:transport-any";
857 char transport_buf[80];
858 const char* transport = transport_buf;
859 socket_handle_t sock;
860 ssize_t result;
862 sock = adb_connect(server_ip, server_tcp_port);
863 if (sock == INVALID_SOCKET) {
864 ws_warning("Error while connecting to adb server");
865 return sock;
868 if (!serial_number) {
869 transport = adb_transport_any;
870 } else {
871 result = snprintf(transport_buf, sizeof(transport_buf), adb_transport_serial_templace, serial_number);
872 if (result <= 0 || result > (int)sizeof(transport_buf)) {
873 ws_warning("Error while completing adb packet for transport");
874 closesocket(sock);
875 return INVALID_SOCKET;
879 result = adb_send(sock, transport);
880 if (result) {
881 ws_warning("Error while setting adb transport for <%s>", transport_buf);
882 closesocket(sock);
883 return INVALID_SOCKET;
885 return sock;
889 static void new_interface(extcap_parameters * extcap_conf, const char *interface_id,
890 const char *model_name, const char *serial_number, const char *display_name)
892 char *interface = ws_strdup_printf("%s-%s", interface_id, serial_number);
893 char *ifdisplay = ws_strdup_printf("%s %s %s", display_name, model_name, serial_number);
895 if (is_specified_interface(interface, INTERFACE_ANDROID_BLUETOOTH_HCIDUMP) ||
896 is_specified_interface(interface, INTERFACE_ANDROID_BLUETOOTH_EXTERNAL_PARSER) ||
897 is_specified_interface(interface, INTERFACE_ANDROID_BLUETOOTH_BTSNOOP_NET)) {
899 extcap_base_register_interface_ext(extcap_conf, interface, ifdisplay, 99, "BluetoothH4", "Bluetooth HCI UART transport layer plus pseudo-header" );
900 } else if (is_logcat_interface(interface) || is_logcat_text_interface(interface)) {
901 extcap_base_register_interface(extcap_conf, interface, ifdisplay, 252, "Upper PDU" );
902 } else if (is_specified_interface(interface, INTERFACE_ANDROID_TCPDUMP)) {
903 extcap_base_register_interface(extcap_conf, interface, ifdisplay, 1, "Ethernet");
905 g_free(interface);
906 g_free(ifdisplay);
910 static void new_fake_interface_for_list_dlts(extcap_parameters * extcap_conf,
911 const char *ifname)
913 if (is_specified_interface(ifname, INTERFACE_ANDROID_BLUETOOTH_HCIDUMP) ||
914 is_specified_interface(ifname, INTERFACE_ANDROID_BLUETOOTH_EXTERNAL_PARSER) ||
915 is_specified_interface(ifname, INTERFACE_ANDROID_BLUETOOTH_BTSNOOP_NET)) {
916 extcap_base_register_interface_ext(extcap_conf, ifname, ifname, 99, "BluetoothH4", "Bluetooth HCI UART transport layer plus pseudo-header" );
917 } else if (is_logcat_interface(ifname) || is_logcat_text_interface(ifname)) {
918 extcap_base_register_interface(extcap_conf, ifname, ifname, 252, "Upper PDU" );
919 } else if (is_specified_interface(ifname, INTERFACE_ANDROID_TCPDUMP)) {
920 extcap_base_register_interface(extcap_conf, ifname, ifname, 1, "Ethernet");
925 static int add_tcpdump_interfaces(extcap_parameters * extcap_conf, const char *adb_server_ip, unsigned short *adb_server_tcp_port, const char *serial_number)
927 static const char *const adb_tcpdump_list = "shell:tcpdump -D";
928 static const char *const regex_ifaces = "\\d+\\.(?<iface>\\S+)(\\s+?(?:(?:\\(.*\\))*)(\\s*?\\[(?<flags>.*?)\\])?)?";
929 static char recv_buffer[PACKET_LENGTH];
930 char *response;
931 ssize_t data_length;
932 socket_handle_t sock;
933 GRegex* regex = NULL;
934 GError *err = NULL;
935 GMatchInfo *match = NULL;
936 char* tok;
937 char iface_name[80];
938 bool flags_supported;
940 sock = adb_connect_transport(adb_server_ip, adb_server_tcp_port, serial_number);
941 if (sock == INVALID_SOCKET) {
942 ws_warning("Failed to connect to adb server");
943 return EXIT_CODE_GENERIC;
946 response = adb_send_and_read(sock, adb_tcpdump_list, recv_buffer, sizeof(recv_buffer), &data_length);
947 closesocket(sock);
949 if (!response) {
950 ws_warning("Failed to get list of available tcpdump interfaces");
951 return EXIT_CODE_GENERIC;
953 response[data_length] = '\0';
955 regex = g_regex_new(regex_ifaces, G_REGEX_RAW, (GRegexMatchFlags)0, &err);
956 if (!regex) {
957 ws_warning("Failed to compile regex for tcpdump interface matching");
958 return EXIT_CODE_GENERIC;
961 flags_supported = (strstr(response, "[") != 0) && (strstr(response, "]") != 0);
963 tok = strtok(response, "\n");
964 while (tok != NULL) {
965 g_regex_match(regex, tok, (GRegexMatchFlags)0, &match);
966 if (g_match_info_matches(match)) {
967 char *iface = g_match_info_fetch_named(match, "iface");
968 char *flags = g_match_info_fetch_named(match, "flags");
970 if (!flags_supported || (flags && strstr(flags, "Up"))) {
971 snprintf(iface_name, sizeof(iface_name), INTERFACE_ANDROID_TCPDUMP_FORMAT, iface);
972 new_interface(extcap_conf, iface_name, iface, serial_number, "Android tcpdump");
974 g_free(flags);
975 g_free(iface);
977 g_match_info_free(match);
978 tok = strtok(NULL, "\n");
980 g_regex_unref(regex);
981 return 0;
985 static int register_interfaces(extcap_parameters * extcap_conf, const char *adb_server_ip, unsigned short *adb_server_tcp_port) {
986 static char packet[PACKET_LENGTH];
987 static char helpful_packet[PACKET_LENGTH];
988 char check_port_buf[80];
989 char *response;
990 char *device_list;
991 ssize_t data_length;
992 size_t device_length;
993 socket_handle_t sock;
994 const char *adb_check_port_templace = "shell:cat /proc/%s/net/tcp";
995 const char *adb_devices = "host:devices-l";
996 const char *adb_api_level = "shell:getprop ro.build.version.sdk";
997 const char *adb_hcidump_version = "shell:hcidump --version";
998 const char *adb_ps_droid_bluetooth = "shell:ps droid.bluetooth";
999 const char *adb_ps_bluetooth_app = "shell:ps com.android.bluetooth";
1000 const char *adb_ps_with_grep = "shell:ps | grep com.android.bluetooth";
1001 const char *adb_ps_all_with_grep = "shell:ps -A | grep com.*android.bluetooth";
1002 char serial_number[SERIAL_NUMBER_LENGTH_MAX];
1003 char model_name[MODEL_NAME_LENGTH_MAX];
1004 int result;
1005 char *pos;
1006 char *i_pos;
1007 char *model_pos;
1008 char *device_pos;
1009 char *prev_pos;
1010 int api_level;
1011 int disable_interface;
1013 /* NOTE: It seems that "adb devices" and "adb shell" closed connection
1014 so cannot send next command after them, there is need to reconnect */
1016 sock = adb_connect(adb_server_ip, adb_server_tcp_port);
1017 if (sock == INVALID_SOCKET)
1018 return EXIT_CODE_INVALID_SOCKET_INTERFACES_LIST;
1020 device_list = adb_send_and_receive(sock, adb_devices, packet, sizeof(packet), &device_length);
1021 closesocket(sock);
1023 if (!device_list) {
1024 ws_warning("Cannot get list of interfaces from devices");
1026 return EXIT_CODE_CANNOT_GET_INTERFACES_LIST;
1029 device_list[device_length] = '\0';
1030 pos = (char *) device_list;
1032 while (pos < (char *) (device_list + device_length)) {
1033 prev_pos = pos;
1034 pos = strchr(pos, ' ');
1035 i_pos = pos;
1036 result = (int) (pos - prev_pos);
1037 pos = strchr(pos, '\n') + 1;
1038 if (result >= (int) sizeof(serial_number)) {
1039 ws_warning("Serial number too long, ignore device");
1040 continue;
1042 memcpy(serial_number, prev_pos, result);
1043 serial_number[result] = '\0';
1045 model_name[0] = '\0';
1046 model_pos = g_strstr_len(i_pos, pos - i_pos, "model:");
1047 if (model_pos) {
1048 device_pos = g_strstr_len(i_pos, pos - i_pos, "device:");
1049 if (device_pos && device_pos - model_pos - 6 - 1 < MODEL_NAME_LENGTH_MAX) {
1050 memcpy(model_name, model_pos + 6, device_pos - model_pos - 6 - 1);
1051 model_name[device_pos - model_pos - 6 - 1] = '\0';
1055 if (model_name[0] == '\0')
1056 strcpy(model_name, "unknown");
1058 ws_debug("Processing device: \"%s\" <%s>" , serial_number, model_name);
1060 /* Function will only add tcpdump interfaces if tcpdump is present on the device */
1061 result = add_tcpdump_interfaces(extcap_conf, adb_server_ip, adb_server_tcp_port, serial_number );
1062 if (result) {
1063 ws_warning("Error while adding tcpdump interfaces");
1066 sock = adb_connect_transport(adb_server_ip, adb_server_tcp_port, serial_number);
1067 if (sock == INVALID_SOCKET) continue;
1069 response = adb_send_and_read(sock, adb_api_level, helpful_packet, sizeof(helpful_packet), &data_length);
1070 closesocket(sock);
1072 if (!response) {
1073 ws_warning("Error on socket: <%s>", helpful_packet);
1074 continue;
1077 response[data_length] = '\0';
1078 api_level = (int) g_ascii_strtoll(response, NULL, 10);
1079 ws_debug("Android API Level for %s is %i", serial_number, api_level);
1081 if (api_level < 21) {
1082 new_interface(extcap_conf, INTERFACE_ANDROID_LOGCAT_MAIN, model_name, serial_number, "Android Logcat Main");
1083 new_interface(extcap_conf, INTERFACE_ANDROID_LOGCAT_SYSTEM, model_name, serial_number, "Android Logcat System");
1084 new_interface(extcap_conf, INTERFACE_ANDROID_LOGCAT_RADIO, model_name, serial_number, "Android Logcat Radio");
1085 new_interface(extcap_conf, INTERFACE_ANDROID_LOGCAT_EVENTS, model_name, serial_number, "Android Logcat Events");
1087 new_interface(extcap_conf, INTERFACE_ANDROID_LOGCAT_TEXT_MAIN, model_name, serial_number, "Android Logcat Main");
1088 new_interface(extcap_conf, INTERFACE_ANDROID_LOGCAT_TEXT_SYSTEM, model_name, serial_number, "Android Logcat System");
1089 new_interface(extcap_conf, INTERFACE_ANDROID_LOGCAT_TEXT_RADIO, model_name, serial_number, "Android Logcat Radio");
1090 new_interface(extcap_conf, INTERFACE_ANDROID_LOGCAT_TEXT_EVENTS, model_name, serial_number, "Android Logcat Events");
1091 } else {
1092 new_interface(extcap_conf, INTERFACE_ANDROID_LOGCAT_TEXT_MAIN, model_name, serial_number, "Android Logcat Main");
1093 new_interface(extcap_conf, INTERFACE_ANDROID_LOGCAT_TEXT_SYSTEM, model_name, serial_number, "Android Logcat System");
1094 new_interface(extcap_conf, INTERFACE_ANDROID_LOGCAT_TEXT_RADIO, model_name, serial_number, "Android Logcat Radio");
1095 new_interface(extcap_conf, INTERFACE_ANDROID_LOGCAT_TEXT_EVENTS, model_name, serial_number, "Android Logcat Events");
1096 new_interface(extcap_conf, INTERFACE_ANDROID_LOGCAT_TEXT_CRASH, model_name, serial_number, "Android Logcat Crash");
1099 if (api_level >= 5 && api_level < 17) {
1100 disable_interface = 0;
1102 sock = adb_connect_transport(adb_server_ip, adb_server_tcp_port, serial_number);
1103 if (sock == INVALID_SOCKET) continue;
1105 response = adb_send_and_read(sock, adb_hcidump_version, helpful_packet, sizeof(helpful_packet), &data_length);
1106 closesocket(sock);
1108 if (!response || data_length < 1) {
1109 ws_warning("Error while getting hcidump version by <%s> (%p len=%"PRIdMAX")",
1110 adb_hcidump_version, (void*)response, (intmax_t)data_length);
1111 ws_debug("Android hcidump version for %s is unknown", serial_number);
1112 disable_interface = 1;
1113 } else {
1114 response[data_length] = '\0';
1116 if (g_ascii_strtoull(response, NULL, 10) == 0) {
1117 ws_debug("Android hcidump version for %s is unknown", serial_number);
1118 disable_interface = 1;
1119 } else {
1120 ws_debug("Android hcidump version for %s is %s", serial_number, response);
1124 if (!disable_interface) {
1125 new_interface(extcap_conf, INTERFACE_ANDROID_BLUETOOTH_HCIDUMP, model_name, serial_number, "Android Bluetooth Hcidump");
1129 if (api_level >= 17 && api_level < 21) {
1130 disable_interface = 0;
1131 sock = adb_connect_transport(adb_server_ip, adb_server_tcp_port, serial_number);
1132 if (sock == INVALID_SOCKET) continue;
1134 response = adb_send_and_read(sock, adb_ps_droid_bluetooth, helpful_packet, sizeof(helpful_packet), &data_length);
1135 closesocket(sock);
1136 if (!response || data_length < 1) {
1137 ws_warning("Error while getting Bluetooth application process id by <%s> "
1138 "(%p len=%"PRIdMAX")", adb_ps_droid_bluetooth, (void*)response, (intmax_t)data_length);
1139 ws_debug( "Android Bluetooth application PID for %s is unknown", serial_number);
1140 disable_interface = 1;
1141 } else {
1142 char *data_str;
1143 char pid[16];
1145 memset(pid, 0, sizeof(pid));
1146 response[data_length] = '\0';
1148 data_str = strchr(response, '\n');
1149 if (data_str && sscanf(data_str, "%*s %15s", pid) == 1) {
1150 ws_debug("Android Bluetooth application PID for %s is %s", serial_number, pid);
1152 result = snprintf(check_port_buf, sizeof(check_port_buf), adb_check_port_templace, pid);
1153 if (result <= 0 || result > (int)sizeof(check_port_buf)) {
1154 ws_warning("Error while completing adb packet");
1155 return EXIT_CODE_BAD_SIZE_OF_ASSEMBLED_ADB_PACKET_6;
1158 sock = adb_connect_transport(adb_server_ip, adb_server_tcp_port, serial_number);
1159 if (sock == INVALID_SOCKET) continue;
1161 response = adb_send_and_read(sock, check_port_buf, helpful_packet, sizeof(helpful_packet), &data_length);
1162 closesocket(sock);
1164 if (!response) {
1165 disable_interface = 1;
1166 } else {
1167 response[data_length] = '\0';
1169 data_str = strchr(response, '\n');
1170 if (data_str && sscanf(data_str, "%*s %15s", pid) == 1 && strlen(pid) > 10 && strcmp(pid + 9, "10EA") == 0) {
1171 ws_debug("Bluedroid External Parser Port for %s is %s", serial_number, pid + 9);
1172 } else {
1173 disable_interface = 1;
1174 ws_debug("Bluedroid External Parser Port for %s is unknown", serial_number);
1177 } else {
1178 disable_interface = 1;
1179 ws_debug("Android Bluetooth application PID for %s is unknown", serial_number);
1183 if (!disable_interface) {
1184 new_interface(extcap_conf, INTERFACE_ANDROID_BLUETOOTH_EXTERNAL_PARSER, model_name, serial_number, "Android Bluetooth External Parser");
1188 if (api_level >= 21) {
1189 const char* ps_cmd;
1190 disable_interface = 0;
1192 if (api_level >= 26) {
1193 ps_cmd = adb_ps_all_with_grep;
1194 } else if (api_level >= 24) {
1195 ps_cmd = adb_ps_with_grep;
1196 } else if (api_level >= 23) {
1197 ps_cmd = adb_ps_bluetooth_app;
1198 } else {
1199 ps_cmd = adb_ps_droid_bluetooth;
1201 sock = adb_connect_transport(adb_server_ip, adb_server_tcp_port, serial_number);
1202 if (sock == INVALID_SOCKET) continue;
1204 response = adb_send_and_read(sock, ps_cmd, helpful_packet, sizeof(helpful_packet), &data_length);
1205 closesocket(sock);
1207 if (!response || data_length < 1) {
1208 ws_warning("Error while getting Bluetooth application process id by <%s> "
1209 "(%p len=%"PRIdMAX")", ps_cmd, (void*)response, (intmax_t)data_length);
1210 ws_debug("Android Bluetooth application PID for %s is unknown", serial_number);
1211 disable_interface = 1;
1212 } else {
1213 char *data_str;
1214 char pid[16];
1216 memset(pid, 0, sizeof(pid));
1217 response[data_length] = '\0';
1219 if (api_level >= 24)
1220 data_str = response;
1221 else
1222 data_str = strchr(response, '\n');
1224 if (data_str && sscanf(data_str, "%*s %15s", pid) == 1) {
1225 ws_debug("Android Bluetooth application PID for %s is %s", serial_number, pid);
1227 result = snprintf(check_port_buf, sizeof(check_port_buf), adb_check_port_templace, pid);
1228 if (result <= 0 || result > (int)sizeof(check_port_buf)) {
1229 ws_warning("Error while completing adb packet");
1230 return EXIT_CODE_BAD_SIZE_OF_ASSEMBLED_ADB_PACKET_9;
1233 sock = adb_connect_transport(adb_server_ip, adb_server_tcp_port, serial_number);
1234 if (sock == INVALID_SOCKET) continue;
1236 response = adb_send_and_read(sock, check_port_buf, helpful_packet, sizeof(helpful_packet), &data_length);
1237 closesocket(sock);
1239 if (!response) {
1240 disable_interface = 1;
1241 } else {
1242 response[data_length] = '\0';
1243 data_str = strtok(response, "\n");
1244 while (data_str != NULL) {
1245 if (sscanf(data_str, "%*s %15s", pid) == 1 && strlen(pid) > 10 && strcmp(pid + 9, "22A8") == 0) {
1246 ws_debug("Btsnoop Net Port for %s is %s", serial_number, pid + 9);
1247 break;
1249 data_str = strtok(NULL, "\n");
1251 if (data_str == NULL) {
1252 disable_interface = 1;
1253 ws_debug("Btsnoop Net Port for %s is unknown", serial_number);
1256 } else {
1257 disable_interface = 1;
1258 ws_debug("Android Bluetooth application PID for %s is unknown", serial_number);
1262 if (!disable_interface) {
1263 new_interface(extcap_conf, INTERFACE_ANDROID_BLUETOOTH_BTSNOOP_NET, model_name, serial_number, "Android Bluetooth Btsnoop Net");
1268 return EXIT_CODE_SUCCESS;
1271 static int list_config(char *interface) {
1272 int ret = EXIT_CODE_INVALID_INTERFACE;
1273 unsigned inc = 0;
1275 if (!interface) {
1276 ws_warning("No interface specified.");
1277 return EXIT_CODE_NO_INTERFACE_SPECIFIED;
1280 if (is_specified_interface(interface, INTERFACE_ANDROID_BLUETOOTH_EXTERNAL_PARSER)) {
1281 printf("arg {number=%u}{call=--adb-server-ip}{display=ADB Server IP Address}{type=string}{default=127.0.0.1}\n", inc++);
1282 printf("arg {number=%u}{call=--adb-server-tcp-port}{display=ADB Server TCP Port}{type=integer}{range=0,65535}{default=5037}\n", inc++);
1283 printf("arg {number=%u}{call=--bt-server-tcp-port}{display=Bluetooth Server TCP Port}{type=integer}{range=0,65535}{default=4330}\n", inc++);
1284 printf("arg {number=%u}{call=--bt-forward-socket}{display=Forward Bluetooth Socket}{type=boolean}{default=false}\n", inc++);
1285 printf("arg {number=%u}{call=--bt-local-ip}{display=Bluetooth Local IP Address}{type=string}{default=127.0.0.1}\n", inc++);
1286 printf("arg {number=%u}{call=--bt-local-tcp-port}{display=Bluetooth Local TCP Port}{type=integer}{range=0,65535}{default=4330}{tooltip=Used to do \"adb forward tcp:LOCAL_TCP_PORT tcp:SERVER_TCP_PORT\"}\n", inc++);
1287 ret = EXIT_CODE_SUCCESS;
1288 } else if (is_specified_interface(interface, INTERFACE_ANDROID_BLUETOOTH_HCIDUMP) ||
1289 is_specified_interface(interface, INTERFACE_ANDROID_BLUETOOTH_BTSNOOP_NET) ||
1290 is_specified_interface(interface, INTERFACE_ANDROID_TCPDUMP)) {
1291 printf("arg {number=%u}{call=--adb-server-ip}{display=ADB Server IP Address}{type=string}{default=127.0.0.1}\n", inc++);
1292 printf("arg {number=%u}{call=--adb-server-tcp-port}{display=ADB Server TCP Port}{type=integer}{range=0,65535}{default=5037}\n", inc++);
1293 ret = EXIT_CODE_SUCCESS;
1294 } else if (is_logcat_interface(interface)) {
1295 printf("arg {number=%u}{call=--adb-server-ip}{display=ADB Server IP Address}{type=string}{default=127.0.0.1}\n", inc++);
1296 printf("arg {number=%u}{call=--adb-server-tcp-port}{display=ADB Server TCP Port}{type=integer}{range=0,65535}{default=5037}\n", inc++);
1297 printf("arg {number=%u}{call=--logcat-text}{display=Use text logcat}{type=boolean}{default=false}\n", inc++);
1298 printf("arg {number=%u}{call=--logcat-ignore-log-buffer}{display=Ignore log buffer}{type=boolean}{default=false}\n", inc++);
1299 printf("arg {number=%u}{call=--logcat-custom-options}{display=Custom logcat parameters}{type=string}\n", inc++);
1300 ret = EXIT_CODE_SUCCESS;
1301 } else if (is_logcat_text_interface(interface)) {
1302 printf("arg {number=%u}{call=--adb-server-ip}{display=ADB Server IP Address}{type=string}{default=127.0.0.1}\n", inc++);
1303 printf("arg {number=%u}{call=--adb-server-tcp-port}{display=ADB Server TCP Port}{type=integer}{range=0,65535}{default=5037}\n", inc++);
1304 printf("arg {number=%u}{call=--logcat-ignore-log-buffer}{display=Ignore log buffer}{type=boolean}{default=false}\n", inc++);
1305 printf("arg {number=%u}{call=--logcat-custom-options}{display=Custom logcat parameters}{type=string}\n", inc++);
1306 ret = EXIT_CODE_SUCCESS;
1309 if (ret != EXIT_CODE_SUCCESS)
1310 ws_warning("Invalid interface: <%s>", interface);
1311 else
1312 extcap_config_debug(&inc);
1314 return ret;
1317 /*----------------------------------------------------------------------------*/
1318 /* Android Bluetooth Hcidump */
1319 /*----------------------------------------------------------------------------*/
1321 static int capture_android_bluetooth_hcidump(char *interface, char *fifo,
1322 const char *adb_server_ip, unsigned short *adb_server_tcp_port) {
1323 struct extcap_dumper extcap_dumper;
1324 static char data[PACKET_LENGTH];
1325 static char packet[PACKET_LENGTH];
1326 ssize_t length;
1327 ssize_t used_buffer_length = 0;
1328 socket_handle_t sock = INVALID_SOCKET;
1329 const char *adb_shell_hcidump = "shell:hcidump -R -t";
1330 const char *adb_shell_su_hcidump = "shell:su -c hcidump -R -t";
1331 int result;
1332 char *serial_number;
1333 time_t ts = 0;
1334 unsigned int captured_length;
1335 int64_t hex;
1336 char *hex_data;
1337 char *new_hex_data;
1338 own_pcap_bluetooth_h4_header *h4_header;
1339 int64_t raw_length = 0;
1340 int64_t frame_length;
1341 int ms = 0;
1342 struct tm date;
1343 char direction_character;
1345 SET_DATA(h4_header, value_own_pcap_bluetooth_h4_header, packet);
1347 extcap_dumper = extcap_dumper_open(fifo, EXTCAP_ENCAP_BLUETOOTH_H4_WITH_PHDR);
1349 serial_number = get_serial_from_interface(interface);
1350 sock = adb_connect_transport(adb_server_ip, adb_server_tcp_port, serial_number);
1351 if (sock == INVALID_SOCKET)
1352 return EXIT_CODE_INVALID_SOCKET_3;
1354 result = adb_send(sock, adb_shell_hcidump);
1355 if (result) {
1356 ws_warning("Error while starting capture by sending command: %s", adb_shell_hcidump);
1357 closesocket(sock);
1358 return EXIT_CODE_GENERIC;
1361 while (endless_loop) {
1362 char *i_position;
1364 errno = 0;
1365 length = recv(sock, data + used_buffer_length, (int)(PACKET_LENGTH - used_buffer_length), 0);
1366 if (errno == EAGAIN
1367 #if EWOULDBLOCK != EAGAIN
1368 || errno == EWOULDBLOCK
1369 #endif
1371 continue;
1373 else if (errno != 0) {
1374 ws_warning("ERROR capture: %s", strerror(errno));
1375 closesocket(sock);
1376 return EXIT_CODE_GENERIC;
1379 if (length <= 0) {
1380 ws_warning("Broken socket connection.");
1381 closesocket(sock);
1382 return EXIT_CODE_GENERIC;
1385 used_buffer_length += length;
1386 i_position = (char *) memchr(data, '\n', used_buffer_length);
1387 if (i_position && i_position < data + used_buffer_length) {
1388 char *state_line_position = i_position + 1;
1390 if (!strncmp(data, "/system/bin/sh: hcidump: not found", 34)) {
1391 ws_warning("Command not found for <%s>", adb_shell_hcidump);
1392 closesocket(sock);
1393 return EXIT_CODE_GENERIC;
1396 i_position = (char *) memchr(i_position + 1, '\n', used_buffer_length);
1397 if (i_position) {
1398 i_position += 1;
1399 if (!strncmp(state_line_position, "Can't access device: Permission denied", 38)) {
1400 ws_warning("No permission for command <%s>", adb_shell_hcidump);
1401 used_buffer_length = 0;
1402 closesocket(sock);
1403 sock = INVALID_SOCKET;
1404 break;
1406 memmove(data, i_position, used_buffer_length - (i_position - data));
1407 used_buffer_length = used_buffer_length - (ssize_t)(i_position - data);
1408 break;
1413 if (sock == INVALID_SOCKET) {
1414 sock = adb_connect_transport(adb_server_ip, adb_server_tcp_port, serial_number);
1415 if (sock == INVALID_SOCKET)
1416 return EXIT_CODE_INVALID_SOCKET_4;
1418 result = adb_send(sock, adb_shell_su_hcidump);
1419 if (result) {
1420 ws_warning("Error while starting capture by sending command: <%s>", adb_shell_su_hcidump);
1421 closesocket(sock);
1422 return EXIT_CODE_GENERIC;
1425 used_buffer_length = 0;
1426 while (endless_loop) {
1427 char *i_position;
1429 errno = 0;
1430 length = recv(sock, data + used_buffer_length, (int)(PACKET_LENGTH - used_buffer_length), 0);
1431 if (errno == EAGAIN
1432 #if EWOULDBLOCK != EAGAIN
1433 || errno == EWOULDBLOCK
1434 #endif
1436 continue;
1438 else if (errno != 0) {
1439 ws_warning("ERROR capture: %s", strerror(errno));
1440 closesocket(sock);
1441 return EXIT_CODE_GENERIC;
1444 if (length <= 0) {
1445 ws_warning("Broken socket connection.");
1446 closesocket(sock);
1447 return EXIT_CODE_GENERIC;
1450 used_buffer_length += length;
1451 i_position = (char *) memchr(data, '\n', used_buffer_length);
1452 if (i_position && i_position < data + used_buffer_length) {
1453 if (!strncmp(data, "/system/bin/sh: su: not found", 29)) {
1454 ws_warning("Command 'su' not found for <%s>", adb_shell_su_hcidump);
1455 closesocket(sock);
1456 return EXIT_CODE_GENERIC;
1459 i_position = (char *) memchr(i_position + 1, '\n', used_buffer_length);
1460 if (i_position) {
1461 i_position += 1;
1462 memmove(data, i_position, used_buffer_length - (i_position - data));
1463 used_buffer_length = used_buffer_length - (ssize_t)(i_position - data);
1464 break;
1470 while (endless_loop) {
1471 errno = 0;
1472 length = recv(sock, data + used_buffer_length, (int)(PACKET_LENGTH - used_buffer_length), 0);
1473 if (errno == EAGAIN
1474 #if EWOULDBLOCK != EAGAIN
1475 || errno == EWOULDBLOCK
1476 #endif
1478 continue;
1480 else if (errno != 0) {
1481 ws_warning("ERROR capture: %s", strerror(errno));
1482 closesocket(sock);
1483 return EXIT_CODE_GENERIC;
1486 if (length <= 0) {
1487 ws_warning("Broken socket connection.");
1488 closesocket(sock);
1489 return EXIT_CODE_GENERIC;
1492 while (endless_loop) {
1493 if (used_buffer_length + length >= 1) {
1494 hex_data = data + 29;
1495 hex = g_ascii_strtoll(hex_data, &new_hex_data, 16);
1497 if ((hex == 0x01 && used_buffer_length + length >= 4) ||
1498 (hex == 0x02 && used_buffer_length + length >= 5) ||
1499 (hex == 0x04 && used_buffer_length + length >= 3)) {
1501 if (hex == 0x01) {
1502 hex_data = new_hex_data;
1503 hex = g_ascii_strtoll(hex_data, &new_hex_data, 16);
1504 if (hex < 0 || hex >= 256 || hex_data == new_hex_data) {
1505 ws_warning("data format %s", strerror(errno));
1506 closesocket(sock);
1507 return EXIT_CODE_GENERIC;
1510 hex_data = new_hex_data;
1511 hex = g_ascii_strtoll(hex_data, &new_hex_data, 16);
1512 if (hex < 0 || hex >= 256 || hex_data == new_hex_data) {
1513 ws_warning("data format %s", strerror(errno));
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);
1521 raw_length = hex + 4;
1522 } else if (hex == 0x04) {
1523 hex_data = new_hex_data;
1524 hex = g_ascii_strtoll(hex_data, &new_hex_data, 16);
1525 if (hex < 0 || hex >= 256 || hex_data == new_hex_data) {
1526 ws_warning("data format %s", strerror(errno));
1527 closesocket(sock);
1528 return EXIT_CODE_GENERIC;
1531 hex_data = new_hex_data;
1532 hex = g_ascii_strtoll(hex_data, &new_hex_data, 16);
1534 raw_length = hex + 3;
1535 } else if (hex == 0x02) {
1536 hex_data = new_hex_data;
1537 hex = g_ascii_strtoll(hex_data, &new_hex_data, 16);
1538 if (hex < 0 || hex >= 256 || hex_data == new_hex_data) {
1539 ws_warning("data format %s", strerror(errno));
1540 closesocket(sock);
1541 return EXIT_CODE_GENERIC;
1544 hex_data = new_hex_data;
1545 hex = g_ascii_strtoll(hex_data, &new_hex_data, 16);
1546 if (hex < 0 || hex >= 256 || hex_data == new_hex_data) {
1547 ws_warning("data format %s", strerror(errno));
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 raw_length = hex + 5;
1556 hex_data = new_hex_data;
1557 hex = g_ascii_strtoll(hex_data, &new_hex_data, 16);
1558 raw_length += hex << 8;
1561 } else {
1562 ws_warning("bad raw stream");
1563 closesocket(sock);
1564 return EXIT_CODE_GENERIC;
1566 } else {
1567 used_buffer_length += length;
1568 break;
1571 frame_length = raw_length * 3 + (raw_length / 20) * 4 + ((raw_length % 20) ? 2 : -2) + 29;
1573 if ((used_buffer_length + length) < frame_length) {
1574 used_buffer_length += length;
1575 break;
1578 if (8 == sscanf(data, "%04d-%02d-%02d %02d:%02d:%02d.%06d %c",
1579 &date.tm_year, &date.tm_mon, &date.tm_mday, &date.tm_hour,
1580 &date.tm_min, &date.tm_sec, &ms, &direction_character)) {
1582 ws_debug("time %04d-%02d-%02d %02d:%02d:%02d.%06d %c",
1583 date.tm_year, date.tm_mon, date.tm_mday, date.tm_hour,
1584 date.tm_min, date.tm_sec, ms, direction_character);
1585 date.tm_mon -= 1;
1586 date.tm_year -= 1900;
1587 date.tm_isdst = -1;
1588 ts = mktime(&date);
1590 new_hex_data = data + 29;
1593 captured_length = 0;
1595 while ((long)(new_hex_data - data + sizeof(own_pcap_bluetooth_h4_header)) < frame_length) {
1596 hex_data = new_hex_data;
1597 hex = g_ascii_strtoll(hex_data, &new_hex_data, 16);
1599 packet[sizeof(own_pcap_bluetooth_h4_header) + captured_length] = (char) hex;
1600 captured_length += 1;
1603 h4_header->direction = GINT32_TO_BE(direction_character == '>');
1605 endless_loop = extcap_dumper_dump(extcap_dumper, fifo, packet,
1606 captured_length + sizeof(own_pcap_bluetooth_h4_header),
1607 captured_length + sizeof(own_pcap_bluetooth_h4_header),
1609 ms * 1000);
1611 memmove(data, data + frame_length, (size_t)(used_buffer_length + length - frame_length));
1612 used_buffer_length = (ssize_t)(used_buffer_length + length - frame_length);
1613 length = 0;
1617 closesocket(sock);
1618 return EXIT_CODE_SUCCESS;
1621 /*----------------------------------------------------------------------------*/
1622 /* Android Bluetooth External Parser */
1623 /*----------------------------------------------------------------------------*/
1625 #define BLUEDROID_H4_PACKET_TYPE 0
1626 #define BLUEDROID_TIMESTAMP_SIZE 8
1627 #define BLUEDROID_H4_SIZE 1
1629 static const uint64_t BLUEDROID_TIMESTAMP_BASE = UINT64_C(0x00dcddb30f2f8000);
1631 #define BLUEDROID_H4_PACKET_TYPE_HCI_CMD 0x01
1632 #define BLUEDROID_H4_PACKET_TYPE_ACL 0x02
1633 #define BLUEDROID_H4_PACKET_TYPE_SCO 0x03
1634 #define BLUEDROID_H4_PACKET_TYPE_HCI_EVT 0x04
1636 #define BLUEDROID_DIRECTION_SENT 0
1637 #define BLUEDROID_DIRECTION_RECV 1
1639 static int adb_forward(char *serial_number, const char *adb_server_ip, unsigned short *adb_server_tcp_port,
1640 unsigned short local_tcp_port, unsigned short server_tcp_port) {
1641 socket_handle_t sock;
1642 int result;
1643 static char helpful_packet[PACKET_LENGTH];
1644 static const char *adb_forward_template = "%s%s:forward:tcp:%05u;tcp:%05u";
1646 sock = adb_connect(adb_server_ip, adb_server_tcp_port);
1647 if (sock == INVALID_SOCKET)
1648 return EXIT_CODE_INVALID_SOCKET_5;
1650 result = snprintf(helpful_packet, PACKET_LENGTH, adb_forward_template, (serial_number) ? "host-serial:" : "host", (serial_number) ? serial_number: "", local_tcp_port, server_tcp_port);
1651 if (result <= 0 || result > PACKET_LENGTH) {
1652 ws_warning("Error while completing adb packet");
1653 closesocket(sock);
1654 return EXIT_CODE_BAD_SIZE_OF_ASSEMBLED_ADB_PACKET_12;
1657 result = adb_send(sock, helpful_packet);
1658 closesocket(sock);
1660 return result;
1663 static int capture_android_bluetooth_external_parser(char *interface,
1664 char *fifo, const char *adb_server_ip, unsigned short *adb_server_tcp_port,
1665 unsigned short *bt_server_tcp_port, unsigned int bt_forward_socket, const char *bt_local_ip,
1666 unsigned short *bt_local_tcp_port) {
1667 struct extcap_dumper extcap_dumper;
1668 static char buffer[PACKET_LENGTH];
1669 uint64_t *timestamp;
1670 char *packet = buffer + BLUEDROID_TIMESTAMP_SIZE - sizeof(own_pcap_bluetooth_h4_header); /* skip timestamp (8 bytes) and reuse its space for header */
1671 own_pcap_bluetooth_h4_header *h4_header;
1672 uint8_t *payload = packet + sizeof(own_pcap_bluetooth_h4_header);
1673 const char *adb_tcp_bluedroid_external_parser_template = "tcp:%05u";
1674 socklen_t slen;
1675 ssize_t length;
1676 ssize_t used_buffer_length = 0;
1677 uint64_t ts;
1678 socket_handle_t sock;
1679 struct sockaddr_in server;
1680 int captured_length;
1681 char *serial_number;
1682 static unsigned int id = 1;
1683 struct sockaddr_in client;
1685 SET_DATA(timestamp, value_u64, buffer);
1686 SET_DATA(h4_header, value_own_pcap_bluetooth_h4_header, packet);
1688 extcap_dumper = extcap_dumper_open(fifo, EXTCAP_ENCAP_BLUETOOTH_H4_WITH_PHDR);
1689 serial_number = get_serial_from_interface(interface);
1691 if (bt_forward_socket) {
1692 if ((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET) {
1693 ws_warning("Cannot open system TCP socket: %s", strerror(errno));
1694 return EXIT_CODE_GENERIC;
1697 ws_debug("Using config: Server TCP Port=%u, Local IP=%s, Local TCP Port=%u",
1698 *bt_server_tcp_port, bt_local_ip, *bt_local_tcp_port);
1700 if (*bt_local_tcp_port != 0) {
1701 int result;
1703 result = adb_forward(serial_number, adb_server_ip, adb_server_tcp_port, *bt_local_tcp_port, *bt_server_tcp_port);
1704 ws_debug("DO: adb forward tcp:%u (local) tcp:%u (remote) result=%i",
1705 *bt_local_tcp_port, *bt_server_tcp_port, result);
1708 memset(&server, 0 , sizeof(server));
1709 server.sin_family = AF_INET;
1710 server.sin_port = GINT16_TO_BE(*bt_local_tcp_port);
1711 ws_inet_pton4(bt_local_ip, (ws_in4_addr *)&(server.sin_addr.s_addr));
1713 useSndTimeout(sock);
1715 if (connect(sock, (struct sockaddr *) &server, sizeof(server)) == SOCKET_ERROR) {
1716 ws_warning("<%s> Please check that adb daemon is running.", strerror(errno));
1717 closesocket(sock);
1718 return EXIT_CODE_GENERIC;
1721 slen = (socklen_t)sizeof(client);
1722 if (getsockname(sock, (struct sockaddr *) &client, &slen)) {
1723 ws_warning("getsockname: %s", strerror(errno));
1724 closesocket(sock);
1725 return EXIT_CODE_GENERIC;
1728 if (slen != sizeof(client)) {
1729 ws_warning("incorrect length");
1730 closesocket(sock);
1731 return EXIT_CODE_GENERIC;
1734 ws_debug("Client port %u", GUINT16_FROM_BE(client.sin_port));
1735 } else {
1736 int result;
1738 sock = adb_connect_transport(adb_server_ip, adb_server_tcp_port, serial_number);
1739 if (sock == INVALID_SOCKET)
1740 return EXIT_CODE_INVALID_SOCKET_6;
1742 result = snprintf((char *) buffer, PACKET_LENGTH, adb_tcp_bluedroid_external_parser_template, *bt_server_tcp_port);
1743 if (result <= 0 || result > PACKET_LENGTH) {
1744 ws_warning("Error while completing adb packet");
1745 closesocket(sock);
1746 return EXIT_CODE_BAD_SIZE_OF_ASSEMBLED_ADB_PACKET_14;
1749 result = adb_send(sock, buffer);
1750 if (result) {
1751 ws_warning("Error while forwarding adb port");
1752 closesocket(sock);
1753 return EXIT_CODE_GENERIC;
1757 while (endless_loop) {
1758 errno = 0;
1759 length = recv(sock, buffer + used_buffer_length, (int)(PACKET_LENGTH - used_buffer_length), 0);
1760 if (errno == EAGAIN
1761 #if EWOULDBLOCK != EAGAIN
1762 || errno == EWOULDBLOCK
1763 #endif
1765 continue;
1767 else if (errno != 0) {
1768 ws_warning("ERROR capture: %s", strerror(errno));
1769 closesocket(sock);
1770 return EXIT_CODE_GENERIC;
1773 if (length <= 0) {
1774 if (bt_forward_socket) {
1775 /* NOTE: Workaround... It seems that Bluedroid is slower and we can connect to socket that are not really ready... */
1776 ws_warning("Broken socket connection. Try reconnect.");
1777 closesocket(sock);
1779 if ((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET) {
1780 ws_warning("%s", strerror(errno));
1781 return EXIT_CODE_GENERIC;
1784 server.sin_family = AF_INET;
1785 server.sin_port = GINT16_TO_BE(*bt_local_tcp_port);
1786 ws_inet_pton4(bt_local_ip, (ws_in4_addr *)&(server.sin_addr.s_addr));
1788 useSndTimeout(sock);
1790 if (connect(sock, (struct sockaddr *) &server, sizeof(server)) == SOCKET_ERROR) {
1791 ws_warning("ERROR reconnect: <%s> Please check that adb daemon is running.", strerror(errno));
1792 closesocket(sock);
1793 return EXIT_CODE_GENERIC;
1795 } else {
1796 ws_warning("Broken socket connection.");
1797 closesocket(sock);
1798 return EXIT_CODE_GENERIC;
1801 continue;
1804 used_buffer_length += length;
1806 ws_debug("Received: length=%"PRIdMAX, (intmax_t)length);
1808 while (((payload[BLUEDROID_H4_PACKET_TYPE] == BLUEDROID_H4_PACKET_TYPE_HCI_CMD || payload[BLUEDROID_H4_PACKET_TYPE] == BLUEDROID_H4_PACKET_TYPE_SCO) &&
1809 used_buffer_length >= BLUEDROID_TIMESTAMP_SIZE + BLUEDROID_H4_SIZE + 2 + 1 &&
1810 BLUEDROID_TIMESTAMP_SIZE + BLUEDROID_H4_SIZE + 2 + payload[BLUEDROID_H4_SIZE + 2] + 1 <= used_buffer_length) ||
1811 (payload[BLUEDROID_H4_PACKET_TYPE] == BLUEDROID_H4_PACKET_TYPE_ACL &&
1812 used_buffer_length >= BLUEDROID_TIMESTAMP_SIZE + BLUEDROID_H4_SIZE + 2 + 2 &&
1813 BLUEDROID_TIMESTAMP_SIZE + BLUEDROID_H4_SIZE + 2 + payload[BLUEDROID_H4_SIZE + 2] + (payload[BLUEDROID_H4_SIZE + 2 + 1] << 8) + 2 <= used_buffer_length) ||
1814 (payload[BLUEDROID_H4_PACKET_TYPE] == BLUEDROID_H4_PACKET_TYPE_SCO &&
1815 used_buffer_length >= BLUEDROID_TIMESTAMP_SIZE + BLUEDROID_H4_SIZE + 2 + 1 &&
1816 BLUEDROID_TIMESTAMP_SIZE + BLUEDROID_H4_SIZE + 2 + payload[BLUEDROID_H4_SIZE + 2] + 1 <= used_buffer_length) ||
1817 (payload[BLUEDROID_H4_PACKET_TYPE] == BLUEDROID_H4_PACKET_TYPE_HCI_EVT &&
1818 used_buffer_length >= BLUEDROID_TIMESTAMP_SIZE + BLUEDROID_H4_SIZE + 1 + 1 &&
1819 BLUEDROID_TIMESTAMP_SIZE + BLUEDROID_H4_SIZE + 1 + payload[BLUEDROID_H4_SIZE + 1] + 1 <= used_buffer_length)) {
1821 ts = GINT64_FROM_BE(*timestamp);
1823 switch (payload[BLUEDROID_H4_PACKET_TYPE]) {
1824 case BLUEDROID_H4_PACKET_TYPE_HCI_CMD:
1825 h4_header->direction = GINT32_TO_BE(BLUEDROID_DIRECTION_SENT);
1827 captured_length = (unsigned int)sizeof(own_pcap_bluetooth_h4_header) + payload[3] + 4;
1829 length = sizeof(own_pcap_bluetooth_h4_header) + BLUEDROID_H4_SIZE + 2 + 1 + payload[3];
1831 break;
1832 case BLUEDROID_H4_PACKET_TYPE_ACL:
1833 h4_header->direction = (payload[2] & 0x80) ? GINT32_TO_BE(BLUEDROID_DIRECTION_RECV) : GINT32_TO_BE(BLUEDROID_DIRECTION_SENT);
1835 captured_length = (unsigned int)sizeof(own_pcap_bluetooth_h4_header) + payload[3] + (payload[3 + 1] << 8) + 5;
1837 length = sizeof(own_pcap_bluetooth_h4_header) + BLUEDROID_H4_SIZE + 2 + 2 + payload[3] + (ssize_t)(payload[3 + 1] << 8);
1839 break;
1840 case BLUEDROID_H4_PACKET_TYPE_SCO:
1841 h4_header->direction = (payload[2] & 0x80) ? GINT32_TO_BE(BLUEDROID_DIRECTION_RECV) : GINT32_TO_BE(BLUEDROID_DIRECTION_SENT);
1843 captured_length = (unsigned int)sizeof(own_pcap_bluetooth_h4_header) + payload[3] + 4;
1845 length = sizeof(own_pcap_bluetooth_h4_header) + BLUEDROID_H4_SIZE + 2 + 1 + payload[3];
1847 break;
1848 case BLUEDROID_H4_PACKET_TYPE_HCI_EVT:
1849 h4_header->direction = GINT32_TO_BE(BLUEDROID_DIRECTION_RECV);
1851 captured_length = (unsigned int)sizeof(own_pcap_bluetooth_h4_header) + payload[2] + 3;
1853 length = sizeof(own_pcap_bluetooth_h4_header) + BLUEDROID_H4_SIZE + 1 + 1 + payload[2];
1855 break;
1856 default:
1857 ws_warning("Invalid stream");
1858 closesocket(sock);
1859 return EXIT_CODE_GENERIC;
1862 ws_debug("\t Packet %u: used_buffer_length=%"PRIdMAX" length=%"PRIdMAX" captured_length=%i type=0x%02x", id, (intmax_t)used_buffer_length, (intmax_t)length, captured_length, payload[BLUEDROID_H4_PACKET_TYPE]);
1863 if (payload[BLUEDROID_H4_PACKET_TYPE] == BLUEDROID_H4_PACKET_TYPE_HCI_EVT)
1864 ws_debug("\t Packet: %02x %02x %02x", (unsigned int) payload[0], (unsigned int) payload[1], (unsigned int)payload[2]);
1865 id +=1;
1867 ts -= BLUEDROID_TIMESTAMP_BASE;
1869 endless_loop = extcap_dumper_dump(extcap_dumper, fifo, packet,
1870 captured_length,
1871 captured_length,
1872 (uint32_t)(ts / 1000000),
1873 ((uint32_t)(ts % 1000000)) * 1000);
1875 used_buffer_length -= length - sizeof(own_pcap_bluetooth_h4_header) + BLUEDROID_TIMESTAMP_SIZE;
1876 if (used_buffer_length < 0) {
1877 ws_warning("Internal Negative used buffer length.");
1878 closesocket(sock);
1879 return EXIT_CODE_GENERIC;
1881 memmove(buffer, packet + length, used_buffer_length);
1885 closesocket(sock);
1886 return EXIT_CODE_SUCCESS;
1889 /*----------------------------------------------------------------------------*/
1890 /* Android Btsnoop Net */
1891 /*----------------------------------------------------------------------------*/
1893 static int capture_android_bluetooth_btsnoop_net(char *interface, char *fifo,
1894 const char *adb_server_ip, unsigned short *adb_server_tcp_port) {
1895 struct extcap_dumper extcap_dumper;
1896 static char packet[PACKET_LENGTH];
1897 ssize_t length;
1898 ssize_t used_buffer_length = 0;
1899 socket_handle_t sock;
1900 const char *adb_tcp_btsnoop_net = "tcp:8872";
1901 int result;
1902 char *serial_number;
1903 uint64_t ts;
1904 static const uint64_t BTSNOOP_TIMESTAMP_BASE = UINT64_C(0x00dcddb30f2f8000);
1905 uint32_t *reported_length;
1906 uint32_t *captured_length;
1907 uint32_t *flags;
1908 /* uint32_t *cumulative_dropped_packets; */
1909 uint64_t *timestamp;
1910 char *payload = packet + sizeof(own_pcap_bluetooth_h4_header) + 24;
1911 own_pcap_bluetooth_h4_header *h4_header;
1913 SET_DATA(reported_length, value_u32, packet + sizeof(own_pcap_bluetooth_h4_header) + 0);
1914 SET_DATA(captured_length, value_u32, packet + sizeof(own_pcap_bluetooth_h4_header) + 4);
1915 SET_DATA(flags, value_u32, packet + sizeof(own_pcap_bluetooth_h4_header) + 8);
1916 /* SET_DATA(cumulative_dropped_packets, value_u32, packet + sizeof(own_pcap_bluetooth_h4_header) + 12); */
1917 SET_DATA(timestamp, value_u64, packet + sizeof(own_pcap_bluetooth_h4_header) + 16);
1918 SET_DATA(h4_header, value_own_pcap_bluetooth_h4_header, payload - sizeof(own_pcap_bluetooth_h4_header));
1920 extcap_dumper = extcap_dumper_open(fifo, EXTCAP_ENCAP_BLUETOOTH_H4_WITH_PHDR);
1921 serial_number = get_serial_from_interface(interface);
1922 sock = adb_connect_transport(adb_server_ip, adb_server_tcp_port, serial_number);
1923 if (sock == INVALID_SOCKET)
1924 return EXIT_CODE_INVALID_SOCKET_7;
1926 result = adb_send(sock, adb_tcp_btsnoop_net);
1927 if (result) {
1928 ws_warning("Error while sending command <%s>", adb_tcp_btsnoop_net);
1929 closesocket(sock);
1930 return EXIT_CODE_ERROR_WHILE_SENDING_ADB_PACKET_2;
1933 /* Read "btsnoop" header - 16 bytes */
1934 while (used_buffer_length < BTSNOOP_HDR_LEN) {
1935 length = recv(sock, packet + used_buffer_length, (int)(BTSNOOP_HDR_LEN - used_buffer_length), 0);
1936 if (length <= 0) {
1937 ws_warning("Broken socket connection.");
1938 closesocket(sock);
1939 return EXIT_CODE_GENERIC;
1941 used_buffer_length += length;
1943 used_buffer_length = 0;
1945 while (endless_loop) {
1946 errno = 0;
1947 length = recv(sock, packet + used_buffer_length + sizeof(own_pcap_bluetooth_h4_header),
1948 (int)(PACKET_LENGTH - sizeof(own_pcap_bluetooth_h4_header) - used_buffer_length), 0);
1949 if (errno == EAGAIN
1950 #if EWOULDBLOCK != EAGAIN
1951 || errno == EWOULDBLOCK
1952 #endif
1954 continue;
1956 else if (errno != 0) {
1957 ws_warning("ERROR capture: %s", strerror(errno));
1958 closesocket(sock);
1959 return EXIT_CODE_GENERIC;
1962 if (length <= 0) {
1963 ws_warning("Broken socket connection.");
1964 closesocket(sock);
1965 return EXIT_CODE_GENERIC;
1968 used_buffer_length += length;
1970 while (used_buffer_length >= 24 &&
1971 used_buffer_length >= (int) (24 + GINT32_FROM_BE(*captured_length))) {
1972 int32_t direction;
1974 ts = GINT64_FROM_BE(*timestamp);
1975 ts -= BTSNOOP_TIMESTAMP_BASE;
1977 direction = GINT32_FROM_BE(*flags) & 0x01;
1978 h4_header->direction = GINT32_TO_BE(direction);
1980 endless_loop = extcap_dumper_dump(extcap_dumper, fifo,
1981 payload - sizeof(own_pcap_bluetooth_h4_header),
1982 GINT32_FROM_BE(*captured_length) + sizeof(own_pcap_bluetooth_h4_header),
1983 GINT32_FROM_BE(*reported_length) + sizeof(own_pcap_bluetooth_h4_header),
1984 (uint32_t)(ts / 1000000),
1985 ((uint32_t)(ts % 1000000)) * 1000);
1987 used_buffer_length -= 24 + GINT32_FROM_BE(*captured_length);
1988 if (used_buffer_length < 0) {
1989 ws_warning("Internal Negative used buffer length.");
1990 closesocket(sock);
1991 return EXIT_CODE_GENERIC;
1994 if (used_buffer_length > 0)
1995 memmove(packet + sizeof(own_pcap_bluetooth_h4_header), payload + GINT32_FROM_BE(*captured_length), used_buffer_length);
1999 closesocket(sock);
2000 return EXIT_CODE_SUCCESS;
2003 /*----------------------------------------------------------------------------*/
2004 /* Android Logcat Text*/
2005 /*----------------------------------------------------------------------------*/
2008 static int capture_android_logcat_text(char *interface, char *fifo,
2009 const char *adb_server_ip, unsigned short *adb_server_tcp_port,
2010 int logcat_ignore_log_buffer, const char *logcat_custom_parameter) {
2011 struct extcap_dumper extcap_dumper;
2012 static char packet[PACKET_LENGTH];
2013 ssize_t length;
2014 size_t used_buffer_length = 0;
2015 socket_handle_t sock;
2016 const char *protocol_name;
2017 size_t exported_pdu_headers_size = 0;
2018 struct exported_pdu_header exported_pdu_header_protocol_normal;
2019 struct exported_pdu_header *exported_pdu_header_protocol;
2020 struct exported_pdu_header exported_pdu_header_end = {0, 0};
2021 static const char *wireshark_protocol_logcat_text = "logcat_text_threadtime";
2022 const char *adb_logcat_template = "shell:export ANDROID_LOG_TAGS=\"\" ; exec logcat -v threadtime%s%s %s";
2023 char *serial_number = NULL;
2024 int result;
2025 char *pos;
2026 const char *logcat_buffer;
2027 const char *logcat_log_buffer;
2029 extcap_dumper = extcap_dumper_open(fifo, EXTCAP_ENCAP_WIRESHARK_UPPER_PDU);
2031 exported_pdu_header_protocol_normal.tag = GUINT16_TO_BE(EXP_PDU_TAG_DISSECTOR_NAME);
2032 exported_pdu_header_protocol_normal.length = GUINT16_TO_BE(strlen(wireshark_protocol_logcat_text) + 2);
2034 serial_number = get_serial_from_interface(interface);
2035 sock = adb_connect_transport(adb_server_ip, adb_server_tcp_port, serial_number);
2036 if (sock == INVALID_SOCKET)
2037 return EXIT_CODE_INVALID_SOCKET_8;
2039 if (is_specified_interface(interface, INTERFACE_ANDROID_LOGCAT_MAIN) || is_specified_interface(interface, INTERFACE_ANDROID_LOGCAT_TEXT_MAIN))
2040 logcat_buffer = " -b main";
2041 else if (is_specified_interface(interface, INTERFACE_ANDROID_LOGCAT_SYSTEM) || is_specified_interface(interface, INTERFACE_ANDROID_LOGCAT_TEXT_SYSTEM))
2042 logcat_buffer = " -b system";
2043 else if (is_specified_interface(interface, INTERFACE_ANDROID_LOGCAT_RADIO) || is_specified_interface(interface, INTERFACE_ANDROID_LOGCAT_TEXT_RADIO))
2044 logcat_buffer = " -b radio";
2045 else if (is_specified_interface(interface, INTERFACE_ANDROID_LOGCAT_EVENTS) || is_specified_interface(interface, INTERFACE_ANDROID_LOGCAT_TEXT_EVENTS))
2046 logcat_buffer = " -b events";
2047 else if (is_specified_interface(interface, INTERFACE_ANDROID_LOGCAT_TEXT_CRASH))
2048 logcat_buffer = " -b crash";
2049 else {
2050 ws_warning("Unknown interface: <%s>", interface);
2051 closesocket(sock);
2052 return EXIT_CODE_GENERIC;
2055 if (logcat_ignore_log_buffer)
2056 logcat_log_buffer = " -T 1";
2057 else
2058 logcat_log_buffer = "";
2060 if (!logcat_custom_parameter)
2061 logcat_custom_parameter = "";
2063 result = snprintf((char *) packet, PACKET_LENGTH, adb_logcat_template, logcat_buffer, logcat_log_buffer, logcat_custom_parameter);
2064 if (result <= 0 || result > PACKET_LENGTH) {
2065 ws_warning("Error while completing adb packet");
2066 closesocket(sock);
2067 return EXIT_CODE_BAD_SIZE_OF_ASSEMBLED_ADB_PACKET_17;
2070 result = adb_send(sock, packet);
2071 if (result) {
2072 ws_warning("Error while sending command <%s>", packet);
2073 closesocket(sock);
2074 return EXIT_CODE_ERROR_WHILE_SENDING_ADB_PACKET_3;
2077 protocol_name = wireshark_protocol_logcat_text;
2078 exported_pdu_header_protocol = &exported_pdu_header_protocol_normal;
2080 memcpy(packet, exported_pdu_header_protocol, sizeof(struct exported_pdu_header));
2081 exported_pdu_headers_size += sizeof(struct exported_pdu_header);
2083 memcpy(packet + exported_pdu_headers_size, protocol_name, GUINT16_FROM_BE(exported_pdu_header_protocol->length) - 2);
2084 exported_pdu_headers_size += GUINT16_FROM_BE(exported_pdu_header_protocol->length);
2086 packet[exported_pdu_headers_size - 1] = 0;
2087 packet[exported_pdu_headers_size - 2] = 0;
2089 memcpy(packet + exported_pdu_headers_size, &exported_pdu_header_end, sizeof(struct exported_pdu_header));
2090 exported_pdu_headers_size += sizeof(struct exported_pdu_header) + GUINT16_FROM_BE(exported_pdu_header_end.length);
2092 used_buffer_length = 0;
2093 while (endless_loop) {
2094 errno = 0;
2095 length = recv(sock, packet + exported_pdu_headers_size + used_buffer_length, (int)(PACKET_LENGTH - exported_pdu_headers_size - used_buffer_length), 0);
2096 if (errno == EAGAIN
2097 #if EWOULDBLOCK != EAGAIN
2098 || errno == EWOULDBLOCK
2099 #endif
2101 continue;
2103 else if (errno != 0) {
2104 ws_warning("ERROR capture: %s", strerror(errno));
2105 closesocket(sock);
2106 return EXIT_CODE_GENERIC;
2109 if (length <= 0) {
2110 ws_warning("Broken socket connection. Try reconnect.");
2111 closesocket(sock);
2112 return EXIT_CODE_GENERIC;
2115 used_buffer_length += length;
2117 while (used_buffer_length > 0 && (pos = (char *) memchr(packet + exported_pdu_headers_size, '\n', used_buffer_length))) {
2118 int ms;
2119 struct tm* date;
2120 time_t seconds;
2121 time_t secs = 0;
2122 int nsecs = 0;
2123 time_t t;
2125 length = (ssize_t)(pos - packet) + 1;
2127 t = time(NULL);
2128 date = localtime(&t);
2129 if (!date)
2130 continue;
2131 if (6 == sscanf(packet + exported_pdu_headers_size, "%d-%d %d:%d:%d.%d", &date->tm_mon, &date->tm_mday, &date->tm_hour,
2132 &date->tm_min, &date->tm_sec, &ms)) {
2133 date->tm_mon -= 1;
2134 date->tm_isdst = -1;
2135 seconds = mktime(date);
2136 secs = (time_t) seconds;
2137 nsecs = (int) (ms * 1e6);
2140 endless_loop = extcap_dumper_dump(extcap_dumper, fifo, packet,
2141 length,
2142 length,
2143 secs, nsecs);
2145 memmove(packet + exported_pdu_headers_size, packet + length, used_buffer_length + exported_pdu_headers_size - length);
2146 used_buffer_length -= length - exported_pdu_headers_size;
2150 closesocket(sock);
2151 return EXIT_CODE_SUCCESS;
2154 /*----------------------------------------------------------------------------*/
2155 /* Android Logger / Logcat */
2156 /*----------------------------------------------------------------------------*/
2158 static int capture_android_logcat(char *interface, char *fifo,
2159 const char *adb_server_ip, unsigned short *adb_server_tcp_port) {
2160 struct extcap_dumper extcap_dumper;
2161 static char packet[PACKET_LENGTH];
2162 ssize_t length;
2163 size_t used_buffer_length = 0;
2164 socket_handle_t sock;
2165 const char *protocol_name;
2166 size_t exported_pdu_headers_size = 0;
2167 struct exported_pdu_header exported_pdu_header_protocol_events;
2168 struct exported_pdu_header exported_pdu_header_protocol_normal;
2169 struct exported_pdu_header *exported_pdu_header_protocol;
2170 struct exported_pdu_header exported_pdu_header_end = {0, 0};
2171 static const char *wireshark_protocol_logcat = "logcat";
2172 static const char *wireshark_protocol_logcat_events = "logcat_events";
2173 const char *adb_command;
2174 uint16_t *payload_length;
2175 uint16_t *try_header_size;
2176 uint32_t *timestamp_secs;
2177 uint32_t *timestamp_nsecs;
2178 uint16_t header_size;
2179 int result;
2180 char *serial_number = NULL;
2182 extcap_dumper = extcap_dumper_open(fifo, EXTCAP_ENCAP_WIRESHARK_UPPER_PDU);
2184 exported_pdu_header_protocol_events.tag = GUINT16_TO_BE(EXP_PDU_TAG_DISSECTOR_NAME);
2185 exported_pdu_header_protocol_events.length = GUINT16_TO_BE(strlen(wireshark_protocol_logcat_events) + 2);
2187 exported_pdu_header_protocol_normal.tag = GUINT16_TO_BE(EXP_PDU_TAG_DISSECTOR_NAME);
2188 exported_pdu_header_protocol_normal.length = GUINT16_TO_BE(strlen(wireshark_protocol_logcat) + 2);
2190 serial_number = get_serial_from_interface(interface);
2191 sock = adb_connect_transport(adb_server_ip, adb_server_tcp_port, serial_number);
2192 if (sock == INVALID_SOCKET)
2193 return EXIT_CODE_INVALID_SOCKET_9;
2195 adb_command = interface_to_logbuf(interface);
2196 if (!adb_command) {
2197 ws_warning("Unknown interface: <%s>", interface);
2198 closesocket(sock);
2199 return EXIT_CODE_GENERIC;
2202 result = adb_send(sock, adb_command);
2203 if (result) {
2204 ws_warning("Error while sending command <%s>", adb_command);
2205 closesocket(sock);
2206 return EXIT_CODE_ERROR_WHILE_SENDING_ADB_PACKET_4;
2209 if (is_specified_interface(interface, INTERFACE_ANDROID_LOGCAT_EVENTS))
2211 protocol_name = wireshark_protocol_logcat_events;
2212 exported_pdu_header_protocol = &exported_pdu_header_protocol_events;
2213 } else {
2214 protocol_name = wireshark_protocol_logcat;
2215 exported_pdu_header_protocol = &exported_pdu_header_protocol_normal;
2218 memcpy(packet, exported_pdu_header_protocol, sizeof(struct exported_pdu_header));
2219 exported_pdu_headers_size += sizeof(struct exported_pdu_header);
2221 memcpy(packet + exported_pdu_headers_size, protocol_name, GUINT16_FROM_BE(exported_pdu_header_protocol->length) - 2);
2222 exported_pdu_headers_size += GUINT16_FROM_BE(exported_pdu_header_protocol->length);
2224 packet[exported_pdu_headers_size - 1] = 0;
2225 packet[exported_pdu_headers_size - 2] = 0;
2227 memcpy(packet + exported_pdu_headers_size, &exported_pdu_header_end, sizeof(struct exported_pdu_header));
2228 exported_pdu_headers_size += sizeof(struct exported_pdu_header) + GUINT16_FROM_BE(exported_pdu_header_end.length);
2230 SET_DATA(payload_length, value_u16, packet + exported_pdu_headers_size + 0);
2231 SET_DATA(try_header_size, value_u16, packet + exported_pdu_headers_size + 2);
2232 SET_DATA(timestamp_secs, value_u32, packet + exported_pdu_headers_size + 12);
2233 SET_DATA(timestamp_nsecs, value_u32, packet + exported_pdu_headers_size + 16);
2235 while (endless_loop) {
2236 errno = 0;
2237 length = recv(sock, packet + exported_pdu_headers_size + used_buffer_length, (int)(PACKET_LENGTH - exported_pdu_headers_size - used_buffer_length), 0);
2238 if (errno == EAGAIN
2239 #if EWOULDBLOCK != EAGAIN
2240 || errno == EWOULDBLOCK
2241 #endif
2243 continue;
2245 else if (errno != 0) {
2246 ws_warning("ERROR capture: %s", strerror(errno));
2247 closesocket(sock);
2248 return EXIT_CODE_GENERIC;
2251 if (length <= 0) {
2252 while (endless_loop) {
2253 ws_warning("Broken socket connection. Try reconnect.");
2254 used_buffer_length = 0;
2255 closesocket(sock);
2257 sock = adb_connect_transport(adb_server_ip, adb_server_tcp_port, serial_number);
2258 if (sock == INVALID_SOCKET)
2259 return EXIT_CODE_INVALID_SOCKET_10;
2261 result = adb_send(sock, adb_command);
2262 if (result) {
2263 ws_warning("WARNING: Error while sending command <%s>", adb_command);
2264 continue;
2267 break;
2271 used_buffer_length += length + exported_pdu_headers_size;
2273 if (*try_header_size != 24)
2274 header_size = 20;
2275 else
2276 header_size = *try_header_size;
2278 length = (*payload_length) + header_size + (ssize_t)exported_pdu_headers_size;
2280 while (used_buffer_length >= exported_pdu_headers_size + header_size && (size_t)length <= used_buffer_length) {
2281 endless_loop = extcap_dumper_dump(extcap_dumper, fifo, packet,
2282 length,
2283 length,
2284 *timestamp_secs, *timestamp_nsecs);
2286 memmove(packet + exported_pdu_headers_size, packet + length, used_buffer_length - length);
2287 used_buffer_length -= length;
2288 used_buffer_length += exported_pdu_headers_size;
2291 length = (*payload_length) + header_size + (ssize_t)exported_pdu_headers_size;
2293 if (*try_header_size != 24)
2294 header_size = 20;
2295 else
2296 header_size = *try_header_size;
2298 used_buffer_length -= exported_pdu_headers_size;
2301 closesocket(sock);
2303 return EXIT_CODE_SUCCESS;
2307 /*----------------------------------------------------------------------------*/
2308 /* Android Wifi Tcpdump */
2309 /* The Tcpdump sends data in pcap format. So for using the extcap_dumper we */
2310 /* need to unpack the pcap and then send the packet data to the dumper. */
2311 /*----------------------------------------------------------------------------*/
2312 static int capture_android_tcpdump(char *interface, char *fifo,
2313 char *capture_filter, const char *adb_server_ip,
2314 unsigned short *adb_server_tcp_port) {
2315 static const char *const adb_shell_tcpdump_format = "exec:tcpdump -U -n -s 0 -u -i %s -w - %s 2>/dev/null";
2316 static const char *const regex_interface = INTERFACE_ANDROID_TCPDUMP "-(?<iface>.*?)-(?<serial>.*)";
2317 struct extcap_dumper extcap_dumper;
2318 static char data[PACKET_LENGTH];
2319 ssize_t length;
2320 ssize_t used_buffer_length = 0;
2321 ssize_t frame_length=0;
2322 socket_handle_t sock;
2323 int result;
2324 char *iface = NULL;
2325 char *serial_number = NULL;
2326 bool nanosecond_timestamps;
2327 bool swap_byte_order;
2328 pcap_hdr_t *global_header;
2329 pcaprec_hdr_t p_header;
2330 GRegex *regex = NULL;
2331 GError *err = NULL;
2332 GMatchInfo *match = NULL;
2333 char *tcpdump_cmd = NULL;
2334 char *quoted_filter = NULL;
2336 regex = g_regex_new(regex_interface, G_REGEX_RAW, (GRegexMatchFlags)0, &err);
2337 if (!regex) {
2338 ws_warning("Failed to compile regex for tcpdump interface");
2339 return EXIT_CODE_GENERIC;
2342 g_regex_match(regex, interface, (GRegexMatchFlags)0, &match);
2343 if (!g_match_info_matches(match)) {
2344 ws_warning("Failed to determine iface name and serial number");
2345 g_regex_unref(regex);
2346 return EXIT_CODE_GENERIC;
2349 iface = g_match_info_fetch_named(match, "iface");
2350 serial_number = g_match_info_fetch_named(match, "serial");
2351 g_match_info_free(match);
2352 g_regex_unref(regex);
2354 /* First check for the device if it is connected or not */
2355 sock = adb_connect_transport(adb_server_ip, adb_server_tcp_port, serial_number);
2356 g_free(serial_number);
2357 if (sock == INVALID_SOCKET) {
2358 g_free(iface);
2359 return EXIT_CODE_INVALID_SOCKET_11;
2362 quoted_filter = g_shell_quote(capture_filter ? capture_filter : "");
2363 tcpdump_cmd = ws_strdup_printf(adb_shell_tcpdump_format, iface, quoted_filter);
2364 g_free(iface);
2365 g_free(quoted_filter);
2366 result = adb_send(sock, tcpdump_cmd);
2367 g_free(tcpdump_cmd);
2368 if (result) {
2369 ws_warning("Error while setting adb transport");
2370 closesocket(sock);
2371 return EXIT_CODE_GENERIC;
2374 while (used_buffer_length < PCAP_GLOBAL_HEADER_LENGTH) {
2375 errno = 0;
2376 length = recv(sock, data + used_buffer_length, (int)(PCAP_GLOBAL_HEADER_LENGTH - used_buffer_length), 0);
2377 if (errno == EAGAIN
2378 #if EWOULDBLOCK != EAGAIN
2379 || errno == EWOULDBLOCK
2380 #endif
2382 continue;
2384 else if (errno != 0) {
2385 ws_warning("ERROR capture: %s", strerror(errno));
2386 closesocket(sock);
2387 return EXIT_CODE_GENERIC;
2390 if (length <= 0) {
2391 ws_warning("Broken socket connection.");
2392 closesocket(sock);
2393 return EXIT_CODE_GENERIC;
2396 used_buffer_length += length;
2399 global_header = (pcap_hdr_t*) data;
2400 switch (global_header->magic_number) {
2401 case 0xa1b2c3d4:
2402 swap_byte_order = false;
2403 nanosecond_timestamps = false;
2404 break;
2405 case 0xd4c3b2a1:
2406 swap_byte_order = true;
2407 nanosecond_timestamps = false;
2408 break;
2409 case 0xa1b23c4d:
2410 swap_byte_order = false;
2411 nanosecond_timestamps = true;
2412 break;
2413 case 0x4d3cb2a1:
2414 swap_byte_order = true;
2415 nanosecond_timestamps = true;
2416 break;
2417 default:
2418 ws_warning("Received incorrect magic");
2419 closesocket(sock);
2420 return EXIT_CODE_GENERIC;
2422 int encap = (int)(swap_byte_order ? GUINT32_SWAP_LE_BE(global_header->network) : global_header->network);
2423 #ifndef ANDROIDDUMP_USE_LIBPCAP
2424 encap = wtap_pcap_encap_to_wtap_encap(encap);
2425 #endif
2426 extcap_dumper = extcap_dumper_open(fifo, encap);
2428 used_buffer_length = 0;
2429 while (endless_loop) {
2430 ssize_t offset = 0;
2432 errno = 0;
2433 length = recv(sock, data + used_buffer_length, (int)(PACKET_LENGTH - used_buffer_length), 0);
2434 if (errno == EAGAIN
2435 #if EWOULDBLOCK != EAGAIN
2436 || errno == EWOULDBLOCK
2437 #endif
2439 continue;
2441 else if (errno != 0) {
2442 ws_warning("ERROR capture: %s", strerror(errno));
2443 closesocket(sock);
2444 return EXIT_CODE_GENERIC;
2447 if (length <= 0) {
2448 ws_warning("Broken socket connection.");
2449 closesocket(sock);
2450 return EXIT_CODE_GENERIC;
2453 used_buffer_length += length;
2455 while ((used_buffer_length - offset) > PCAP_RECORD_HEADER_LENGTH) {
2456 p_header = *((pcaprec_hdr_t*) (data + offset));
2457 if (swap_byte_order) {
2458 p_header.ts_sec = GUINT32_SWAP_LE_BE(p_header.ts_sec);
2459 p_header.ts_usec = GUINT32_SWAP_LE_BE(p_header.ts_usec);
2460 p_header.incl_len = GUINT32_SWAP_LE_BE(p_header.incl_len);
2461 p_header.orig_len = GUINT32_SWAP_LE_BE(p_header.orig_len);
2463 if (!nanosecond_timestamps) {
2464 p_header.ts_usec = p_header.ts_usec * 1000;
2467 frame_length = p_header.incl_len + PCAP_RECORD_HEADER_LENGTH;
2468 if ((used_buffer_length - offset) < frame_length) {
2469 break; /* wait for complete packet */
2472 /* It was observed that some times tcpdump reports the length of packet as '0' and that leads to the
2473 * ( Warn Error "Less data was read than was expected" while reading )
2474 * So to avoid this error we are checking for length of packet before passing it to dumper.
2476 if (p_header.incl_len > 0) {
2477 endless_loop = extcap_dumper_dump(extcap_dumper, fifo, data + offset + PCAP_RECORD_HEADER_LENGTH,
2478 p_header.incl_len, p_header.orig_len, p_header.ts_sec, p_header.ts_usec);
2481 offset += frame_length;
2484 if (offset < used_buffer_length) {
2485 memmove(data, data + offset, used_buffer_length - offset);
2487 used_buffer_length -= offset;
2490 closesocket(sock);
2491 return EXIT_CODE_SUCCESS;
2494 int main(int argc, char *argv[]) {
2495 char *err_msg;
2496 int ret = EXIT_CODE_GENERIC;
2497 int option_idx = 0;
2498 int result;
2499 const char *adb_server_ip = NULL;
2500 unsigned short *adb_server_tcp_port = NULL;
2501 unsigned int logcat_text = 0;
2502 unsigned int logcat_ignore_log_buffer = 0;
2503 const char *logcat_custom_parameter = NULL;
2504 const char *default_adb_server_ip = "127.0.0.1";
2505 unsigned short default_adb_server_tcp_port = 5037;
2506 unsigned short local_adb_server_tcp_port;
2507 unsigned short local_bt_server_tcp_port;
2508 unsigned short local_bt_local_tcp_port;
2509 unsigned short *bt_server_tcp_port = NULL;
2510 unsigned int bt_forward_socket = 0;
2511 const char *bt_local_ip = NULL;
2512 unsigned short *bt_local_tcp_port = NULL;
2513 unsigned short default_bt_server_tcp_port = 4330;
2514 const char *default_bt_local_ip = "127.0.0.1";
2515 unsigned short default_bt_local_tcp_port = 4330;
2516 extcap_parameters * extcap_conf = NULL;
2517 char *help_url;
2518 char *help_header = NULL;
2520 /* Set the program name. */
2521 g_set_prgname("androiddump");
2523 cmdarg_err_init(extcap_log_cmdarg_err, extcap_log_cmdarg_err);
2525 /* Initialize log handler early so we can have proper logging during startup. */
2526 extcap_log_init();
2529 * Get credential information for later use.
2531 init_process_policies();
2534 * Attempt to get the pathname of the directory containing the
2535 * executable file.
2537 err_msg = configuration_init(argv[0]);
2538 if (err_msg != NULL) {
2539 ws_warning("Can't get pathname of directory containing the extcap program: %s.",
2540 err_msg);
2541 g_free(err_msg);
2544 init_report_failure_message("androiddump");
2546 extcap_conf = g_new0(extcap_parameters, 1);
2548 help_url = data_file_url("androiddump.html");
2549 extcap_base_set_util_info(extcap_conf, argv[0], ANDROIDDUMP_VERSION_MAJOR, ANDROIDDUMP_VERSION_MINOR,
2550 ANDROIDDUMP_VERSION_RELEASE, help_url);
2551 g_free(help_url);
2553 help_header = ws_strdup_printf(
2554 " %s --extcap-interfaces [--adb-server-ip=<arg>] [--adb-server-tcp-port=<arg>]\n"
2555 " %s --extcap-interface=INTERFACE --extcap-dlts\n"
2556 " %s --extcap-interface=INTERFACE --extcap-config\n"
2557 " %s --extcap-interface=INTERFACE --fifo=PATH_FILENAME --capture\n"
2558 "\nINTERFACE has the form TYPE-DEVICEID:\n"
2559 "\t""For example: "INTERFACE_ANDROID_BLUETOOTH_BTSNOOP_NET"-W3D7N15C29005648""\n"
2560 "\n"
2561 "\tTYPE is one of:\n"
2562 "\t"INTERFACE_ANDROID_LOGCAT_MAIN"\n"
2563 "\t"INTERFACE_ANDROID_LOGCAT_SYSTEM"\n"
2564 "\t"INTERFACE_ANDROID_LOGCAT_RADIO"\n"
2565 "\t"INTERFACE_ANDROID_LOGCAT_EVENTS"\n"
2566 "\t"INTERFACE_ANDROID_LOGCAT_TEXT_MAIN"\n"
2567 "\t"INTERFACE_ANDROID_LOGCAT_TEXT_SYSTEM"\n"
2568 "\t"INTERFACE_ANDROID_LOGCAT_TEXT_RADIO"\n"
2569 "\t"INTERFACE_ANDROID_LOGCAT_TEXT_EVENTS"\n"
2570 "\t"INTERFACE_ANDROID_LOGCAT_TEXT_CRASH"\n"
2571 "\t"INTERFACE_ANDROID_BLUETOOTH_HCIDUMP"\n"
2572 "\t"INTERFACE_ANDROID_BLUETOOTH_EXTERNAL_PARSER"\n"
2573 "\t"INTERFACE_ANDROID_BLUETOOTH_BTSNOOP_NET"\n"
2574 "\t"INTERFACE_ANDROID_TCPDUMP"\n"
2575 "\n"
2576 "\t""DEVICEID is the identifier of the device provided by Android SDK (see \"adb devices\")\n"
2577 "\t""For example: W3D7N15C29005648""\n",
2579 argv[0], argv[0], argv[0], argv[0]);
2580 extcap_help_add_header(extcap_conf, help_header);
2581 g_free(help_header);
2583 extcap_help_add_option(extcap_conf, "--help", "print this help");
2584 extcap_help_add_option(extcap_conf, "--adb-server-ip <IP>", "the IP address of the ADB server");
2585 extcap_help_add_option(extcap_conf, "--adb-server-tcp-port <port>", "the TCP port of the ADB server");
2586 extcap_help_add_option(extcap_conf, "--logcat-text", "use logcat text format");
2587 extcap_help_add_option(extcap_conf, "--logcat-ignore-log-buffer", "ignore log buffer");
2588 extcap_help_add_option(extcap_conf, "--logcat-custom-options <text>", "use custom logcat parameters");
2589 extcap_help_add_option(extcap_conf, "--bt-server-tcp-port <port>", "bluetooth server TCP port");
2590 extcap_help_add_option(extcap_conf, "--bt-forward-socket <path>", "bluetooth forward socket");
2591 extcap_help_add_option(extcap_conf, "--bt-local-ip <IP>", "the bluetooth local IP");
2592 extcap_help_add_option(extcap_conf, "--bt-local-tcp-port <port>", "the bluetooth local TCP port");
2594 ws_opterr = 0;
2595 ws_optind = 0;
2597 if (argc == 1) {
2598 extcap_help_print(extcap_conf);
2599 ret = EXIT_CODE_SUCCESS;
2600 goto end;
2603 while ((result = ws_getopt_long(argc, argv, "", longopts, &option_idx)) != -1) {
2604 switch (result) {
2606 case OPT_VERSION:
2607 extcap_version_print(extcap_conf);
2608 ret = EXIT_CODE_SUCCESS;
2609 goto end;
2610 case OPT_HELP:
2611 extcap_help_print(extcap_conf);
2612 ret = EXIT_CODE_SUCCESS;
2613 goto end;
2614 case OPT_CONFIG_ADB_SERVER_IP:
2615 adb_server_ip = ws_optarg;
2616 break;
2617 case OPT_CONFIG_ADB_SERVER_TCP_PORT:
2618 adb_server_tcp_port = &local_adb_server_tcp_port;
2619 if (!ws_optarg){
2620 ws_warning("Impossible exception. Parameter required argument, but there is no it right now.");
2621 goto end;
2623 if (!ws_strtou16(ws_optarg, NULL, adb_server_tcp_port)) {
2624 ws_warning("Invalid adb server TCP port: %s", ws_optarg);
2625 goto end;
2627 break;
2628 case OPT_CONFIG_LOGCAT_TEXT:
2629 if (ws_optarg && !*ws_optarg)
2630 logcat_text = true;
2631 else
2632 logcat_text = (g_ascii_strncasecmp(ws_optarg, "true", 4) == 0);
2633 break;
2634 case OPT_CONFIG_LOGCAT_IGNORE_LOG_BUFFER:
2635 if (ws_optarg == NULL || (ws_optarg && !*ws_optarg))
2636 logcat_ignore_log_buffer = true;
2637 else
2638 logcat_ignore_log_buffer = (g_ascii_strncasecmp(ws_optarg, "true", 4) == 0);
2639 break;
2640 case OPT_CONFIG_LOGCAT_CUSTOM_OPTIONS:
2641 if (ws_optarg == NULL || (ws_optarg && *ws_optarg == '\0')) {
2642 logcat_custom_parameter = NULL;
2643 break;
2646 if (g_regex_match_simple("(^|\\s)-[bBcDfgLnpPrv]", ws_optarg, G_REGEX_RAW, (GRegexMatchFlags)0)) {
2647 ws_error("Found prohibited option in logcat-custom-options");
2648 return EXIT_CODE_GENERIC;
2651 logcat_custom_parameter = ws_optarg;
2653 break;
2654 case OPT_CONFIG_BT_SERVER_TCP_PORT:
2655 bt_server_tcp_port = &local_bt_server_tcp_port;
2656 if (!ws_optarg){
2657 ws_warning("Impossible exception. Parameter required argument, but there is no it right now.");
2658 goto end;
2660 if (!ws_strtou16(ws_optarg, NULL, bt_server_tcp_port)) {
2661 ws_warning("Invalid bluetooth server TCP port: %s", ws_optarg);
2662 goto end;
2664 break;
2665 case OPT_CONFIG_BT_FORWARD_SOCKET:
2666 bt_forward_socket = (g_ascii_strncasecmp(ws_optarg, "true", 4) == 0);
2667 break;
2668 case OPT_CONFIG_BT_LOCAL_IP:
2669 bt_local_ip = ws_optarg;
2670 break;
2671 case OPT_CONFIG_BT_LOCAL_TCP_PORT:
2672 bt_local_tcp_port = &local_bt_local_tcp_port;
2673 if (!ws_optarg){
2674 ws_warning("Impossible exception. Parameter required argument, but there is no it right now.");
2675 goto end;
2677 if (!ws_strtou16(ws_optarg, NULL, bt_local_tcp_port)) {
2678 ws_warning("Invalid bluetooth local tcp port: %s", ws_optarg);
2679 goto end;
2681 break;
2682 default:
2683 if (!extcap_base_parse_options(extcap_conf, result - EXTCAP_OPT_LIST_INTERFACES, ws_optarg))
2685 ws_warning("Invalid argument <%s>. Try --help.\n", argv[ws_optind - 1]);
2686 goto end;
2691 if (!adb_server_ip)
2692 adb_server_ip = default_adb_server_ip;
2694 if (!adb_server_tcp_port)
2695 adb_server_tcp_port = &default_adb_server_tcp_port;
2697 if (!bt_server_tcp_port)
2698 bt_server_tcp_port = &default_bt_server_tcp_port;
2700 if (!bt_local_ip)
2701 bt_local_ip = default_bt_local_ip;
2703 if (!bt_local_tcp_port)
2704 bt_local_tcp_port = &default_bt_local_tcp_port;
2706 err_msg = ws_init_sockets();
2707 if (err_msg != NULL) {
2708 ws_warning("ERROR: %s", err_msg);
2709 g_free(err_msg);
2710 ws_warning("%s", please_report_bug());
2711 goto end;
2714 extcap_cmdline_debug(argv, argc);
2716 if (extcap_conf->do_list_interfaces)
2717 register_interfaces(extcap_conf, adb_server_ip, adb_server_tcp_port);
2719 /* NOTE:
2720 * extcap implementation calls androiddump --extcap-dlts for each interface.
2721 * The only way to know whether an interface exists or not is to go through the
2722 * whole process of listing all interfaces (i.e. calling register_interfaces
2723 * function). Since being a system resource heavy operation and repeated for
2724 * each interface instead register a fake interface to be returned for dlt
2725 * listing only purpose
2727 if (extcap_conf->do_list_dlts) {
2728 new_fake_interface_for_list_dlts(extcap_conf, extcap_conf->interface);
2731 if (extcap_base_handle_interface(extcap_conf)) {
2732 ret = EXIT_CODE_SUCCESS;
2733 goto end;
2736 if (extcap_conf->show_config) {
2737 ret = list_config(extcap_conf->interface);
2738 goto end;
2741 if (extcap_conf->capture) {
2742 if (extcap_conf->interface && is_logcat_interface(extcap_conf->interface))
2743 if (logcat_text)
2744 ret = capture_android_logcat_text(extcap_conf->interface,
2745 extcap_conf->fifo, adb_server_ip, adb_server_tcp_port,
2746 logcat_ignore_log_buffer, logcat_custom_parameter);
2747 else
2748 ret = capture_android_logcat(extcap_conf->interface,
2749 extcap_conf->fifo, adb_server_ip, adb_server_tcp_port);
2750 else if (extcap_conf->interface && is_logcat_text_interface(extcap_conf->interface))
2751 ret = capture_android_logcat_text(extcap_conf->interface,
2752 extcap_conf->fifo, adb_server_ip, adb_server_tcp_port,
2753 logcat_ignore_log_buffer, logcat_custom_parameter);
2754 else if (extcap_conf->interface && is_specified_interface(extcap_conf->interface, INTERFACE_ANDROID_BLUETOOTH_HCIDUMP))
2755 ret = capture_android_bluetooth_hcidump(extcap_conf->interface, extcap_conf->fifo, adb_server_ip, adb_server_tcp_port);
2756 else if (extcap_conf->interface && is_specified_interface(extcap_conf->interface, INTERFACE_ANDROID_BLUETOOTH_EXTERNAL_PARSER))
2757 ret = capture_android_bluetooth_external_parser(extcap_conf->interface, extcap_conf->fifo, adb_server_ip, adb_server_tcp_port,
2758 bt_server_tcp_port, bt_forward_socket, bt_local_ip, bt_local_tcp_port);
2759 else if (extcap_conf->interface && (is_specified_interface(extcap_conf->interface, INTERFACE_ANDROID_BLUETOOTH_BTSNOOP_NET)))
2760 ret = capture_android_bluetooth_btsnoop_net(extcap_conf->interface, extcap_conf->fifo, adb_server_ip, adb_server_tcp_port);
2761 else if (extcap_conf->interface && (is_specified_interface(extcap_conf->interface,INTERFACE_ANDROID_TCPDUMP)))
2762 ret = capture_android_tcpdump(extcap_conf->interface, extcap_conf->fifo, extcap_conf->capture_filter, adb_server_ip, adb_server_tcp_port);
2764 goto end;
2767 /* no action was given, assume success */
2768 ret = EXIT_CODE_SUCCESS;
2770 end:
2771 /* clean up stuff */
2772 extcap_base_cleanup(&extcap_conf);
2773 #ifndef ANDROIDDUMP_USE_LIBPCAP
2774 wtap_cleanup();
2775 #endif
2777 return ret;
2781 * Editor modelines - https://www.wireshark.org/tools/modelines.html
2783 * Local variables:
2784 * c-basic-offset: 4
2785 * tab-width: 8
2786 * indent-tabs-mode: nil
2787 * End:
2789 * vi: set shiftwidth=4 tabstop=8 expandtab:
2790 * :indentSize=4:tabSize=8:noTabs=true: