1 /* androiddump.c
2 * androiddump is extcap tool used to capture Android specific stuff
3 *
4 * Copyright 2015, Michal Labedzki for Tieto Corporation
5 *
6 * Wireshark - Network traffic analyzer
7 * By Gerald Combs <gerald@wireshark.org>
8 * Copyright 1998 Gerald Combs
9 *
10 * SPDX-License-Identifier: GPL-2.0-or-later
11 */
12 #include "config.h"
13
14 #include "extcap-base.h"
15
16 #include <stdio.h>
17 #include <stdint.h>
18 #include <string.h>
19 #include <errno.h>
20 #include <time.h>
21 #include <wsutil/strtoi.h>
22 #include <wsutil/filesystem.h>
23 #include <wsutil/privileges.h>
24 #include <wsutil/report_message.h>
25 #include <wsutil/please_report_bug.h>
26 #include <wsutil/wslog.h>
27 #include <ui/cmdarg_err.h>
28 #include <wsutil/inet_addr.h>
29 #include <wsutil/exported_pdu_tlvs.h>
30
31 #include "ui/failure_message.h"
32
33 #ifdef HAVE_NETINET_IN_H
34 # include <netinet/in.h>
35 #endif
36
37 #ifdef HAVE_UNISTD_H
38 #include <unistd.h>
39 #endif
40
41 #ifdef HAVE_SYS_SOCKET_H
42 #include <sys/socket.h>
43 #endif
44
45 #ifdef HAVE_ARPA_INET_H
46 #include <arpa/inet.h>
47 #endif
48
49 #ifdef HAVE_SYS_TIME_H
50 #include <sys/time.h>
51 #endif
52
53 /* Configuration options */
54 /* #define ANDROIDDUMP_USE_LIBPCAP */
55
56 #define PCAP_GLOBAL_HEADER_LENGTH 24
57 #define PCAP_RECORD_HEADER_LENGTH 16
58
59 #ifdef ANDROIDDUMP_USE_LIBPCAP
60 #include "wspcap.h"
61 #include <pcap-bpf.h>
62 #include <pcap/bluetooth.h>
63
64 #ifndef DLT_BLUETOOTH_H4_WITH_PHDR
65 #define DLT_BLUETOOTH_H4_WITH_PHDR 201
66 #endif
67
68 #ifndef DLT_WIRESHARK_UPPER_PDU
69 #define DLT_WIRESHARK_UPPER_PDU 252
70 #endif
71
72 #ifndef PCAP_TSTAMP_PRECISION_MICRO
73 #define PCAP_TSTAMP_PRECISION_MICRO 0
74 #endif
75
76 #ifndef PCAP_TSTAMP_PRECISION_NANO
77 #define PCAP_TSTAMP_PRECISION_NANO 1
78 #endif
79 #else
80 #include "wiretap/wtap.h"
81 #include "wiretap/pcap-encap.h"
82 #endif
83
84 #include <cli_main.h>
85
86 #ifdef ANDROIDDUMP_USE_LIBPCAP
87 #define EXTCAP_ENCAP_BLUETOOTH_H4_WITH_PHDR DLT_BLUETOOTH_H4_WITH_PHDR
88 #define EXTCAP_ENCAP_WIRESHARK_UPPER_PDU DLT_WIRESHARK_UPPER_PDU
89 #define EXTCAP_ENCAP_ETHERNET DLT_EN10MB
90 #define EXTCAP_ENCAP_LINUX_SLL DLT_LINUX_SLL
91 #define EXTCAP_ENCAP_IEEE802_11_RADIO DLT_IEEE802_11_RADIO
92 #define EXTCAP_ENCAP_NETLINK DLT_NETLINK
93 #else
94 #define EXTCAP_ENCAP_BLUETOOTH_H4_WITH_PHDR WTAP_ENCAP_BLUETOOTH_H4_WITH_PHDR
95 #define EXTCAP_ENCAP_WIRESHARK_UPPER_PDU WTAP_ENCAP_WIRESHARK_UPPER_PDU
96 #define EXTCAP_ENCAP_ETHERNET WTAP_ENCAP_ETHERNET
97 #define EXTCAP_ENCAP_LINUX_SLL WTAP_ENCAP_SLL
98 #define EXTCAP_ENCAP_IEEE802_11_RADIO WTAP_ENCAP_IEEE_802_11_RADIOTAP
99 #define EXTCAP_ENCAP_NETLINK WTAP_ENCAP_NETLINK
100 #endif
101
102 #define INTERFACE_ANDROID_LOGCAT_MAIN "android-logcat-main"
103 #define INTERFACE_ANDROID_LOGCAT_SYSTEM "android-logcat-system"
104 #define INTERFACE_ANDROID_LOGCAT_RADIO "android-logcat-radio"
105 #define INTERFACE_ANDROID_LOGCAT_EVENTS "android-logcat-events"
106 #define INTERFACE_ANDROID_LOGCAT_TEXT_MAIN "android-logcat-text-main"
107 #define INTERFACE_ANDROID_LOGCAT_TEXT_SYSTEM "android-logcat-text-system"
108 #define INTERFACE_ANDROID_LOGCAT_TEXT_RADIO "android-logcat-text-radio"
109 #define INTERFACE_ANDROID_LOGCAT_TEXT_EVENTS "android-logcat-text-events"
110 #define INTERFACE_ANDROID_LOGCAT_TEXT_CRASH "android-logcat-text-crash"
111 #define INTERFACE_ANDROID_BLUETOOTH_HCIDUMP "android-bluetooth-hcidump"
112 #define INTERFACE_ANDROID_BLUETOOTH_EXTERNAL_PARSER "android-bluetooth-external-parser"
113 #define INTERFACE_ANDROID_BLUETOOTH_BTSNOOP_NET "android-bluetooth-btsnoop-net"
114 #define INTERFACE_ANDROID_TCPDUMP "android-tcpdump"
115 #define INTERFACE_ANDROID_TCPDUMP_FORMAT INTERFACE_ANDROID_TCPDUMP "-%s"
116 #define INTERFACE_ANDROID_TCPDUMP_SERIAL_FORMAT INTERFACE_ANDROID_TCPDUMP_FORMAT "-%s"
117
118 #define ANDROIDDUMP_VERSION_MAJOR "1"
119 #define ANDROIDDUMP_VERSION_MINOR "1"
120 #define ANDROIDDUMP_VERSION_RELEASE "0"
121
122 #define SERIAL_NUMBER_LENGTH_MAX 512
123 #define MODEL_NAME_LENGTH_MAX 64
124
125 #define PACKET_LENGTH 65535
126
127 #define SOCKET_RW_TIMEOUT_MS 2000
128 #define SOCKET_CONNECT_TIMEOUT_TRIES 10
129 #define SOCKET_CONNECT_DELAY_US 1000 /* (1000us = 1ms) * SOCKET_CONNECT_TIMEOUT_TRIES (10) = 10ms worst-case */
130
131 #define ADB_HEX4_FORMAT "%04zx"
132 #define ADB_HEX4_LEN 4
133
134 #define BTSNOOP_HDR_LEN 16
135
136 enum exit_code {
137 EXIT_CODE_SUCCESS = 0,
138 EXIT_CODE_CANNOT_GET_INTERFACES_LIST = 1,
139 EXIT_CODE_UNKNOWN_ENCAPSULATION_WIRETAP,
140 EXIT_CODE_UNKNOWN_ENCAPSULATION_LIBPCAP,
141 EXIT_CODE_CANNOT_SAVE_WIRETAP_DUMP,
142 EXIT_CODE_CANNOT_SAVE_LIBPCAP_DUMP,
143 EXIT_CODE_NO_INTERFACE_SPECIFIED,
144 EXIT_CODE_INVALID_INTERFACE,
145 EXIT_CODE_BAD_SIZE_OF_ASSEMBLED_ADB_PACKET_1,
146 EXIT_CODE_BAD_SIZE_OF_ASSEMBLED_ADB_PACKET_2,
147 EXIT_CODE_BAD_SIZE_OF_ASSEMBLED_ADB_PACKET_3,
148 EXIT_CODE_BAD_SIZE_OF_ASSEMBLED_ADB_PACKET_4,
149 EXIT_CODE_BAD_SIZE_OF_ASSEMBLED_ADB_PACKET_5,
150 EXIT_CODE_BAD_SIZE_OF_ASSEMBLED_ADB_PACKET_6,
151 EXIT_CODE_BAD_SIZE_OF_ASSEMBLED_ADB_PACKET_7,
152 EXIT_CODE_BAD_SIZE_OF_ASSEMBLED_ADB_PACKET_8,
153 EXIT_CODE_BAD_SIZE_OF_ASSEMBLED_ADB_PACKET_9,
154 EXIT_CODE_BAD_SIZE_OF_ASSEMBLED_ADB_PACKET_10,
155 EXIT_CODE_BAD_SIZE_OF_ASSEMBLED_ADB_PACKET_11,
156 EXIT_CODE_BAD_SIZE_OF_ASSEMBLED_ADB_PACKET_12,
157 EXIT_CODE_BAD_SIZE_OF_ASSEMBLED_ADB_PACKET_13,
158 EXIT_CODE_BAD_SIZE_OF_ASSEMBLED_ADB_PACKET_14,
159 EXIT_CODE_BAD_SIZE_OF_ASSEMBLED_ADB_PACKET_15,
160 EXIT_CODE_BAD_SIZE_OF_ASSEMBLED_ADB_PACKET_16,
161 EXIT_CODE_BAD_SIZE_OF_ASSEMBLED_ADB_PACKET_17,
162 EXIT_CODE_BAD_SIZE_OF_ASSEMBLED_ADB_PACKET_18,
163 EXIT_CODE_BAD_SIZE_OF_ASSEMBLED_ADB_PACKET_19,
164 EXIT_CODE_BAD_SIZE_OF_ASSEMBLED_ADB_PACKET_20,
165 EXIT_CODE_ERROR_WHILE_SENDING_ADB_PACKET_1,
166 EXIT_CODE_ERROR_WHILE_SENDING_ADB_PACKET_2,
167 EXIT_CODE_ERROR_WHILE_SENDING_ADB_PACKET_3,
168 EXIT_CODE_ERROR_WHILE_SENDING_ADB_PACKET_4,
169 EXIT_CODE_ERROR_WHILE_RECEIVING_ADB_PACKET_STATUS,
170 EXIT_CODE_ERROR_WHILE_RECEIVING_ADB_PACKET_DATA,
171 EXIT_CODE_INVALID_SOCKET_INTERFACES_LIST,
172 EXIT_CODE_INVALID_SOCKET_1,
173 EXIT_CODE_INVALID_SOCKET_2,
174 EXIT_CODE_INVALID_SOCKET_3,
175 EXIT_CODE_INVALID_SOCKET_4,
176 EXIT_CODE_INVALID_SOCKET_5,
177 EXIT_CODE_INVALID_SOCKET_6,
178 EXIT_CODE_INVALID_SOCKET_7,
179 EXIT_CODE_INVALID_SOCKET_8,
180 EXIT_CODE_INVALID_SOCKET_9,
181 EXIT_CODE_INVALID_SOCKET_10,
182 EXIT_CODE_INVALID_SOCKET_11,
183 EXIT_CODE_GENERIC = -1
184 };
185
186 enum {
187 EXTCAP_BASE_OPTIONS_ENUM,
188 OPT_HELP,
189 OPT_VERSION,
190 OPT_CONFIG_ADB_SERVER_IP,
191 OPT_CONFIG_ADB_SERVER_TCP_PORT,
192 OPT_CONFIG_LOGCAT_TEXT,
193 OPT_CONFIG_LOGCAT_IGNORE_LOG_BUFFER,
194 OPT_CONFIG_LOGCAT_CUSTOM_OPTIONS,
195 OPT_CONFIG_BT_SERVER_TCP_PORT,
196 OPT_CONFIG_BT_FORWARD_SOCKET,
197 OPT_CONFIG_BT_LOCAL_IP,
198 OPT_CONFIG_BT_LOCAL_TCP_PORT
199 };
200
201 static struct ws_option longopts[] = {
202 EXTCAP_BASE_OPTIONS,
203 { "help", ws_no_argument, NULL, OPT_HELP},
204 { "version", ws_no_argument, NULL, OPT_VERSION},
205 { "adb-server-ip", ws_required_argument, NULL, OPT_CONFIG_ADB_SERVER_IP},
206 { "adb-server-tcp-port", ws_required_argument, NULL, OPT_CONFIG_ADB_SERVER_TCP_PORT},
207 { "logcat-text", ws_optional_argument, NULL, OPT_CONFIG_LOGCAT_TEXT},
208 { "logcat-ignore-log-buffer", ws_optional_argument, NULL, OPT_CONFIG_LOGCAT_IGNORE_LOG_BUFFER},
209 { "logcat-custom-options", ws_required_argument, NULL, OPT_CONFIG_LOGCAT_CUSTOM_OPTIONS},
210 { "bt-server-tcp-port", ws_required_argument, NULL, OPT_CONFIG_BT_SERVER_TCP_PORT},
211 { "bt-forward-socket", ws_required_argument, NULL, OPT_CONFIG_BT_FORWARD_SOCKET},
212 { "bt-local-ip", ws_required_argument, NULL, OPT_CONFIG_BT_LOCAL_IP},
213 { "bt-local-tcp-port", ws_required_argument, NULL, OPT_CONFIG_BT_LOCAL_TCP_PORT},
214 { 0, 0, 0, 0 }
215 };
216
217 struct interface_t {
218 const char *display_name;
219 const char *interface_name;
220 struct interface_t *next;
221 };
222
223 struct exported_pdu_header {
224 uint16_t tag;
225 uint16_t length;
226 /* unsigned char value[0]; */
227 };
228
229
230 typedef struct _own_pcap_bluetooth_h4_header {
231 uint32_t direction;
232 } own_pcap_bluetooth_h4_header;
233
234 typedef struct pcap_hdr_s {
235 guint32 magic_number; /* magic number */
236 guint16 version_major; /* major version number */
237 guint16 version_minor; /* minor version number */
238 gint32 thiszone; /* GMT to local correction */
239 guint32 sigfigs; /* accuracy of timestamps */
240 guint32 snaplen; /* max length of captured packets, in octets */
241 guint32 network; /* data link type */
242 } pcap_hdr_t;
243
244
245 typedef struct pcaprec_hdr_s {
246 guint32 ts_sec; /* timestamp seconds */
247 guint32 ts_usec; /* timestamp microseconds */
248 guint32 incl_len; /* number of octets of packet saved in file */
249 guint32 orig_len; /* actual length of packet */
250 } pcaprec_hdr_t;
251
252 /* This fix compilator warning like "warning: cast from 'char *' to 'uint32_t *' (aka 'unsigned int *') increases required alignment from 1 to 4 " */
253 typedef union {
254 char *value_char;
255 uint8_t *value_u8;
256 uint16_t *value_u16;
257 uint32_t *value_u32;
258 uint64_t *value_u64;
259 int8_t *value_i8;
260 int16_t *value_i16;
261 int32_t *value_i32;
262 int64_t *value_i64;
263 own_pcap_bluetooth_h4_header *value_own_pcap_bluetooth_h4_header;
264 } data_aligned_t;
265
266 #define SET_DATA(dest, type, src) \
267 { \
268 data_aligned_t data_aligned; \
269 \
270 data_aligned.value_char = src; \
271 dest = data_aligned.type; \
272 }
273
274 struct extcap_dumper {
275 int encap;
276 union {
277 #ifdef ANDROIDDUMP_USE_LIBPCAP
278 pcap_dumper_t *pcap;
279 #else
280 wtap_dumper *wtap;
281 #endif
282 } dumper;
283 };
284
285 /* Globals */
286 static int endless_loop = 1;
287
288 /* Functions */
is_specified_interface(const char * interface,const char * interface_prefix)289 static inline int is_specified_interface(const char *interface, const char *interface_prefix) {
290 return !strncmp(interface, interface_prefix, strlen(interface_prefix));
291 }
292
is_logcat_interface(const char * interface)293 static gboolean is_logcat_interface(const char *interface) {
294 return is_specified_interface(interface, INTERFACE_ANDROID_LOGCAT_MAIN) ||
295 is_specified_interface(interface, INTERFACE_ANDROID_LOGCAT_SYSTEM) ||
296 is_specified_interface(interface, INTERFACE_ANDROID_LOGCAT_RADIO) ||
297 is_specified_interface(interface, INTERFACE_ANDROID_LOGCAT_EVENTS);
298 }
299
is_logcat_text_interface(const char * interface)300 static gboolean is_logcat_text_interface(const char *interface) {
301 return is_specified_interface(interface, INTERFACE_ANDROID_LOGCAT_TEXT_MAIN) ||
302 is_specified_interface(interface, INTERFACE_ANDROID_LOGCAT_TEXT_SYSTEM) ||
303 is_specified_interface(interface, INTERFACE_ANDROID_LOGCAT_TEXT_RADIO) ||
304 is_specified_interface(interface, INTERFACE_ANDROID_LOGCAT_TEXT_EVENTS) ||
305 is_specified_interface(interface, INTERFACE_ANDROID_LOGCAT_TEXT_CRASH);
306 }
307
get_serial_from_interface(char * interface)308 static char* get_serial_from_interface(char *interface)
309 {
310 static const char* const iface_prefix[] = {
311 INTERFACE_ANDROID_LOGCAT_MAIN,
312 INTERFACE_ANDROID_LOGCAT_SYSTEM,
313 INTERFACE_ANDROID_LOGCAT_RADIO,
314 INTERFACE_ANDROID_LOGCAT_EVENTS,
315 INTERFACE_ANDROID_LOGCAT_TEXT_MAIN,
316 INTERFACE_ANDROID_LOGCAT_TEXT_SYSTEM,
317 INTERFACE_ANDROID_LOGCAT_TEXT_RADIO,
318 INTERFACE_ANDROID_LOGCAT_TEXT_EVENTS,
319 INTERFACE_ANDROID_LOGCAT_TEXT_CRASH,
320 INTERFACE_ANDROID_BLUETOOTH_HCIDUMP,
321 INTERFACE_ANDROID_BLUETOOTH_EXTERNAL_PARSER,
322 INTERFACE_ANDROID_BLUETOOTH_BTSNOOP_NET,
323 NULL
324 };
325 int i;
326 const char* curr = NULL;
327 for (i = 0; (curr = iface_prefix[i]); i++) {
328 if (is_specified_interface(interface, curr) &&
329 strlen(interface) > strlen(curr) + 1) {
330 return interface + strlen(curr) + 1;
331 }
332 }
333 return NULL;
334 }
335
interface_to_logbuf(char * interface)336 static const char* interface_to_logbuf(char* interface)
337 {
338 const char *const adb_log_main = "log:main";
339 const char *const adb_log_system = "log:system";
340 const char *const adb_log_radio = "log:radio";
341 const char *const adb_log_events = "log:events";
342 const char *logbuf = NULL;
343
344 if (is_specified_interface(interface, INTERFACE_ANDROID_LOGCAT_MAIN))
345 logbuf = adb_log_main;
346 else if (is_specified_interface(interface, INTERFACE_ANDROID_LOGCAT_SYSTEM))
347 logbuf = adb_log_system;
348 else if (is_specified_interface(interface, INTERFACE_ANDROID_LOGCAT_RADIO))
349 logbuf = adb_log_radio;
350 else if (is_specified_interface(interface, INTERFACE_ANDROID_LOGCAT_EVENTS))
351 logbuf = adb_log_events;
352 return logbuf;
353 }
354
355 /*
356 * General errors and warnings are reported through ws_warning() in
357 * androiddump.
358 *
359 * Unfortunately, ws_warning() may be a macro, so we do it by calling
360 * g_logv() with the appropriate arguments.
361 */
362 static void
androiddump_cmdarg_err(const char * msg_format,va_list ap)363 androiddump_cmdarg_err(const char *msg_format, va_list ap)
364 {
365 ws_logv(LOG_DOMAIN_CAPCHILD, LOG_LEVEL_WARNING, msg_format, ap);
366 }
367
useSndTimeout(socket_handle_t sock)368 static void useSndTimeout(socket_handle_t sock) {
369 int res;
370 #ifdef _WIN32
371 const DWORD socket_timeout = SOCKET_RW_TIMEOUT_MS;
372
373 res = setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, (const char *) &socket_timeout, (socklen_t)sizeof(socket_timeout));
374 #else
375 const struct timeval socket_timeout = {
376 .tv_sec = SOCKET_RW_TIMEOUT_MS / 1000,
377 .tv_usec = (SOCKET_RW_TIMEOUT_MS % 1000) * 1000
378 };
379
380 res = setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, &socket_timeout, (socklen_t)sizeof(socket_timeout));
381 #endif
382 if (res != 0)
383 ws_debug("Can't set socket timeout, using default");
384 }
385
useNonBlockingConnectTimeout(socket_handle_t sock)386 static void useNonBlockingConnectTimeout(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 = 1;
392
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
396 /* set socket to non-blocking */
397 ioctlsocket(sock, FIONBIO, &non_blocking);
398 #else
399 const struct timeval socket_timeout = {
400 .tv_sec = SOCKET_RW_TIMEOUT_MS / 1000,
401 .tv_usec = (SOCKET_RW_TIMEOUT_MS % 1000) * 1000
402 };
403
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");
411 }
412
useNormalConnectTimeout(socket_handle_t sock)413 static void useNormalConnectTimeout(socket_handle_t sock) {
414 int res_rcv;
415 #ifdef _WIN32
416 const DWORD socket_timeout = 0;
417 unsigned long non_blocking = 0;
418
419 res_rcv = setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (const char *) &socket_timeout, sizeof(socket_timeout));
420 ioctlsocket(sock, FIONBIO, &non_blocking);
421 #else
422 const struct timeval socket_timeout = {
423 .tv_sec = SOCKET_RW_TIMEOUT_MS / 1000,
424 .tv_usec = (SOCKET_RW_TIMEOUT_MS % 1000) * 1000
425 };
426
427 res_rcv = setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &socket_timeout, sizeof(socket_timeout));
428 #endif
429 if (res_rcv != 0)
430 ws_debug("Can't set socket timeout, using default");
431 }
432
extcap_dumper_open(char * fifo,int encap)433 static struct extcap_dumper extcap_dumper_open(char *fifo, int encap) {
434 struct extcap_dumper extcap_dumper;
435
436 #ifdef ANDROIDDUMP_USE_LIBPCAP
437 pcap_t *pcap;
438
439 pcap = pcap_open_dead_with_tstamp_precision(encap, PACKET_LENGTH, PCAP_TSTAMP_PRECISION_NANO);
440 extcap_dumper.dumper.pcap = pcap_dump_open(pcap, fifo);
441 if (!extcap_dumper.dumper.pcap) {
442 ws_warning("Can't open %s for saving packets: %s", fifo, pcap_geterr(pcap));
443 pcap_close(pcap);
444 exit(EXIT_CODE_CANNOT_SAVE_LIBPCAP_DUMP);
445 }
446 extcap_dumper.encap = encap;
447 if (pcap_dump_flush(extcap_dumper.dumper.pcap) == -1) {
448 ws_warning("Write to %s failed: %s", fifo, g_strerror(errno));
449 }
450 #else
451 wtap_dump_params params = WTAP_DUMP_PARAMS_INIT;
452 int file_type_subtype;
453 int err = 0;
454 gchar *err_info = NULL;
455
456 wtap_init(FALSE);
457
458 params.encap = encap;
459 params.snaplen = PACKET_LENGTH;
460 file_type_subtype = wtap_pcap_nsec_file_type_subtype();
461 extcap_dumper.dumper.wtap = wtap_dump_open(fifo, file_type_subtype, WTAP_UNCOMPRESSED, ¶ms, &err, &err_info);
462 if (!extcap_dumper.dumper.wtap) {
463 cfile_dump_open_failure_message(fifo, err, err_info, file_type_subtype);
464 exit(EXIT_CODE_CANNOT_SAVE_WIRETAP_DUMP);
465 }
466 extcap_dumper.encap = encap;
467 if (!wtap_dump_flush(extcap_dumper.dumper.wtap, &err)) {
468 cfile_dump_open_failure_message(fifo, err, NULL, file_type_subtype);
469 exit(EXIT_CODE_CANNOT_SAVE_WIRETAP_DUMP);
470 }
471 #endif
472
473 return extcap_dumper;
474 }
475
extcap_dumper_dump(struct extcap_dumper extcap_dumper,char * fifo,char * buffer,gssize captured_length,gssize reported_length,time_t seconds,int nanoseconds)476 static gboolean extcap_dumper_dump(struct extcap_dumper extcap_dumper,
477 char *fifo, char *buffer,
478 gssize captured_length, gssize reported_length,
479 time_t seconds, int nanoseconds) {
480 #ifdef ANDROIDDUMP_USE_LIBPCAP
481 struct pcap_pkthdr pcap_header;
482
483 pcap_header.caplen = (bpf_u_int32) captured_length;
484 pcap_header.len = (bpf_u_int32) reported_length;
485 pcap_header.ts.tv_sec = seconds;
486 pcap_header.ts.tv_usec = nanoseconds / 1000;
487
488 pcap_dump((u_char *) extcap_dumper.dumper.pcap, &pcap_header, buffer);
489 if (pcap_dump_flush(extcap_dumper.dumper.pcap) == -1) {
490 ws_warning("Write to %s failed: %s", fifo, g_strerror(errno));
491 }
492 #else
493 int err = 0;
494 char *err_info;
495 wtap_rec rec;
496
497 rec.rec_type = REC_TYPE_PACKET;
498 rec.presence_flags = WTAP_HAS_TS;
499 rec.rec_header.packet_header.caplen = (guint32) captured_length;
500 rec.rec_header.packet_header.len = (guint32) reported_length;
501
502 rec.ts.secs = seconds;
503 rec.ts.nsecs = (int) nanoseconds;
504
505 rec.block = NULL;
506
507 /* NOTE: Try to handle pseudoheaders manually */
508 if (extcap_dumper.encap == EXTCAP_ENCAP_BLUETOOTH_H4_WITH_PHDR) {
509 uint32_t *direction;
510
511 SET_DATA(direction, value_u32, buffer)
512
513 rec.rec_header.packet_header.pseudo_header.bthci.sent = GINT32_FROM_BE(*direction) ? 0 : 1;
514
515 rec.rec_header.packet_header.len -= (guint32)sizeof(own_pcap_bluetooth_h4_header);
516 rec.rec_header.packet_header.caplen -= (guint32)sizeof(own_pcap_bluetooth_h4_header);
517
518 buffer += sizeof(own_pcap_bluetooth_h4_header);
519 }
520 rec.rec_header.packet_header.pkt_encap = extcap_dumper.encap;
521
522 if (!wtap_dump(extcap_dumper.dumper.wtap, &rec, (const guint8 *) buffer, &err, &err_info)) {
523 cfile_write_failure_message(NULL, fifo, err, err_info, 0,
524 wtap_dump_file_type_subtype(extcap_dumper.dumper.wtap));
525 return FALSE;
526 }
527
528 if (!wtap_dump_flush(extcap_dumper.dumper.wtap, &err)) {
529 cfile_write_failure_message(NULL, fifo, err, NULL, 0,
530 wtap_dump_file_type_subtype(extcap_dumper.dumper.wtap));
531 return FALSE;
532 }
533 #endif
534
535 return TRUE;
536 }
537
538
adb_connect(const char * server_ip,unsigned short * server_tcp_port)539 static socket_handle_t adb_connect(const char *server_ip, unsigned short *server_tcp_port) {
540 socket_handle_t sock;
541 socklen_t length;
542 struct sockaddr_in server;
543 struct sockaddr_in client;
544 int status;
545 int tries = 0;
546
547 memset(&server, 0x0, sizeof(server));
548
549 server.sin_family = AF_INET;
550 server.sin_port = GINT16_TO_BE(*server_tcp_port);
551 ws_inet_pton4(server_ip, &(server.sin_addr.s_addr));
552
553 if ((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET) {
554 ws_warning("Cannot open system TCP socket: %s", strerror(errno));
555 return INVALID_SOCKET;
556 }
557
558 useNonBlockingConnectTimeout(sock);
559 while (tries < SOCKET_CONNECT_TIMEOUT_TRIES) {
560 status = connect(sock, (struct sockaddr *) &server, (socklen_t)sizeof(server));
561 tries += 1;
562
563 #ifdef _WIN32
564 if ((status == SOCKET_ERROR) && (WSAGetLastError() == WSAEWOULDBLOCK)) {
565 const struct timeval timeout = {
566 .tv_sec = 0,
567 .tv_usec = SOCKET_CONNECT_DELAY_US,
568 };
569 fd_set fdset;
570 FD_ZERO(&fdset);
571 FD_SET(sock, &fdset);
572 if ((select(0, NULL, &fdset, NULL, &timeout) != 0) && (FD_ISSET(sock, &fdset))) {
573 status = 0;
574 }
575 }
576 #endif
577
578 if (status != SOCKET_ERROR)
579 break;
580 g_usleep(SOCKET_CONNECT_DELAY_US);
581 }
582 useNormalConnectTimeout(sock);
583
584 if (status == SOCKET_ERROR) {
585 #if 0
586 /* NOTE: This does not work well - make significant delay while initializing Wireshark.
587 Do fork() then call "adb" also does not make sense, because there is need to
588 do something like sleep(1) to ensure adb is started... system() cannot be used
589 on Windows, because open console window. This helper does not work as expected,
590 so disable it and user must ensure that adb is started (adb start-server,
591 but also all other command start-server automatically)
592 */
593 #ifdef _WIN32
594 if (_execlp("adb", "adb", "start-server", NULL)) {
595 #else
596 if (execlp("adb", "adb", "start-server", NULL)) {
597 #endif
598 errmsg("WARNING: Cannot execute system command to start adb: %s", strerror(errno));
599 closesocket(sock);
600 return INVALID_SOCKET;
601 };
602
603 if (connect(sock, (struct sockaddr *) &server, (socklen_t)sizeof(server)) == SOCKET_ERROR) {
604 ws_warning("Cannot connect to ADB: <%s> Please check that adb daemon is running.", strerror(errno));
605 closesocket(sock);
606 return INVALID_SOCKET;
607 }
608 #else
609 ws_debug("Cannot connect to ADB: <%s> Please check that adb daemon is running.", strerror(errno));
610 closesocket(sock);
611 return INVALID_SOCKET;
612 #endif
613 }
614
615 length = sizeof(client);
616 if (getsockname(sock, (struct sockaddr *) &client, &length)) {
617 ws_warning("getsockname: %s", strerror(errno));
618 closesocket(sock);
619 return INVALID_SOCKET;
620 }
621
622 if (length != sizeof(client)) {
623 ws_warning("incorrect length");
624 closesocket(sock);
625 return INVALID_SOCKET;
626 }
627
628 ws_debug("Client port %u", GUINT16_FROM_BE(client.sin_port));
629
630 return sock;
631 }
632
633
634 static char *adb_send_and_receive(socket_handle_t sock, const char *adb_service,
635 char *buffer, size_t buffer_length, size_t *data_length) {
636 size_t used_buffer_length;
637 size_t bytes_to_read;
638 guint32 length;
639 gssize result;
640 char status[4];
641 char tmp_buffer;
642 size_t adb_service_length;
643
644 adb_service_length = strlen(adb_service);
645 if (adb_service_length > INT_MAX) {
646 ws_warning("Service name too long when sending <%s> to ADB daemon", adb_service);
647 if (data_length)
648 *data_length = 0;
649 return NULL;
650 }
651
652 /* 8 bytes of hex length + terminating NUL */
653 if (buffer_length < 9) {
654 ws_warning("Buffer for response too short while sending <%s> to ADB daemon", adb_service);
655 if (data_length)
656 *data_length = 0;
657 return NULL;
658 }
659
660 g_snprintf(buffer, (gulong)buffer_length, ADB_HEX4_FORMAT, adb_service_length);
661 result = send(sock, buffer, ADB_HEX4_LEN, 0);
662 if (result < ADB_HEX4_LEN) {
663 ws_warning("Error while sending <%s> length to ADB daemon", adb_service);
664 return NULL;
665 }
666
667 result = send(sock, adb_service, (int) adb_service_length, 0);
668 if (result != (gssize) adb_service_length) {
669 ws_warning("Error while sending <%s> to ADB daemon", adb_service);
670 if (data_length)
671 *data_length = 0;
672 return NULL;
673 }
674
675 used_buffer_length = 0;
676 while (used_buffer_length < 8) {
677 bytes_to_read = buffer_length - used_buffer_length;
678 if (bytes_to_read > INT_MAX)
679 bytes_to_read = INT_MAX;
680 result = recv(sock, buffer + used_buffer_length, (int)bytes_to_read, 0);
681
682 if (result <= 0) {
683 ws_warning("Broken socket connection while fetching reply status for <%s>", adb_service);
684 if (data_length)
685 *data_length = 0;
686 return NULL;
687 }
688
689 used_buffer_length += result;
690 }
691
692 memcpy(status, buffer, 4);
693 tmp_buffer = buffer[8];
694 buffer[8] = '\0';
695 if (!ws_hexstrtou32(buffer + 4, NULL, &length)) {
696 ws_warning("Invalid reply length <%s> while reading reply for <%s>", buffer + 4, adb_service);
697 if (data_length)
698 *data_length = 0;
699 return NULL;
700 }
701 buffer[8] = tmp_buffer;
702
703 if (buffer_length < length + 8) {
704 ws_warning("Buffer for response too short while sending <%s> to ADB daemon", adb_service);
705 if (data_length)
706 *data_length = 0;
707 return NULL;
708 }
709
710 while (used_buffer_length < length + 8) {
711 bytes_to_read = buffer_length - used_buffer_length;
712 if (bytes_to_read > INT_MAX)
713 bytes_to_read = INT_MAX;
714 result = recv(sock, buffer + used_buffer_length, (int)bytes_to_read, 0);
715
716 if (result <= 0) {
717 ws_warning("Broken socket connection while reading reply for <%s>", adb_service);
718 if (data_length)
719 *data_length = 0;
720 return NULL;
721 }
722
723 used_buffer_length += result;
724 }
725
726 if (data_length)
727 *data_length = used_buffer_length - 8;
728
729 if (memcmp(status, "OKAY", 4)) {
730 ws_warning("Error while receiving by ADB for <%s>", adb_service);
731 if (data_length)
732 *data_length = 0;
733 return NULL;
734 }
735
736 return buffer + 8;
737 }
738
739
740 static char *adb_send_and_read(socket_handle_t sock, const char *adb_service, char *buffer,
741 int buffer_length, gssize *data_length) {
742 gssize used_buffer_length;
743 gssize result;
744 char status[4];
745 size_t adb_service_length;
746
747 adb_service_length = strlen(adb_service);
748 g_snprintf(buffer, buffer_length, ADB_HEX4_FORMAT, adb_service_length);
749
750 result = send(sock, buffer, ADB_HEX4_LEN, 0);
751 if (result < ADB_HEX4_LEN) {
752 ws_warning("Error while sending <%s> to ADB daemon", adb_service);
753 return NULL;
754 }
755
756 result = send(sock, adb_service, (int) adb_service_length, 0);
757 if (result != (gssize) adb_service_length) {
758 ws_warning("Error while sending <%s> to ADB", adb_service);
759 if (data_length)
760 *data_length = 0;
761 return NULL;
762 }
763
764 used_buffer_length = 0;
765 while (used_buffer_length < 4) {
766 result = recv(sock, buffer + used_buffer_length, (int)(buffer_length - used_buffer_length), 0);
767
768 if (result <= 0) {
769 ws_warning("Broken socket connection while fetching reply status for <%s>", adb_service);
770
771 return NULL;
772 }
773
774 used_buffer_length += result;
775 }
776
777 memcpy(status, buffer, 4);
778
779 while (result > 0) {
780 result= recv(sock, buffer + used_buffer_length, (int)(buffer_length - used_buffer_length), 0);
781
782 if (result < 0) {
783 ws_warning("Broken socket connection while reading reply for <%s>", adb_service);
784
785 return NULL;
786 } else if (result == 0) {
787 break;
788 }
789
790 used_buffer_length += result;
791 }
792
793 if (data_length)
794 *data_length = used_buffer_length - 4;
795
796 if (memcmp(status, "OKAY", 4)) {
797 ws_warning("Error while receiving by ADB for <%s>", adb_service);
798 if (data_length)
799 *data_length = 0;
800 return NULL;
801 }
802
803 return buffer + 4;
804 }
805
806
807 static int adb_send(socket_handle_t sock, const char *adb_service) {
808 char buffer[5];
809 int used_buffer_length;
810 gssize result;
811 size_t adb_service_length;
812
813 adb_service_length = strlen(adb_service);
814 g_snprintf(buffer, sizeof(buffer), ADB_HEX4_FORMAT, adb_service_length);
815
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;
820 }
821
822 result = send(sock, adb_service, (int) adb_service_length, 0);
823 if (result != (gssize) adb_service_length) {
824 ws_warning("Error while sending <%s> to ADB", adb_service);
825 return EXIT_CODE_ERROR_WHILE_SENDING_ADB_PACKET_1;
826 }
827
828 used_buffer_length = 0;
829 while (used_buffer_length < 4) {
830 result = recv(sock, buffer + used_buffer_length, 4 - used_buffer_length, 0);
831
832 if (result <= 0) {
833 ws_warning("Broken socket connection while fetching reply status for <%s>", adb_service);
834
835 return EXIT_CODE_ERROR_WHILE_RECEIVING_ADB_PACKET_STATUS;
836 }
837
838 used_buffer_length += (int)result;
839 }
840
841 if (memcmp(buffer, "OKAY", 4)) {
842 ws_debug("Error while receiving by ADB for <%s>", adb_service);
843
844 return EXIT_CODE_ERROR_WHILE_RECEIVING_ADB_PACKET_DATA;
845 }
846
847 return EXIT_CODE_SUCCESS;
848 }
849
850
851 static socket_handle_t
852 adb_connect_transport(const char *server_ip, unsigned short *server_tcp_port,
853 const char* serial_number)
854 {
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 gssize result;
861
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;
866 }
867
868 if (!serial_number) {
869 transport = adb_transport_any;
870 } else {
871 result = g_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;
876 }
877 }
878
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;
884 }
885 return sock;
886 }
887
888
889 static void new_interface(extcap_parameters * extcap_conf, const gchar *interface_id,
890 const gchar *model_name, const gchar *serial_number, const gchar *display_name)
891 {
892 char *interface = g_strdup_printf("%s-%s", interface_id, serial_number);
893 char *ifdisplay = g_strdup_printf("%s %s %s", display_name, model_name, serial_number);
894
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)) {
898
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");
904 }
905 g_free(interface);
906 g_free(ifdisplay);
907 }
908
909
910 static void new_fake_interface_for_list_dlts(extcap_parameters * extcap_conf,
911 const gchar *ifname)
912 {
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");
921 }
922 }
923
924
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)
926 {
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 gssize 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 gboolean flags_supported;
939
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;
944 }
945
946 response = adb_send_and_read(sock, adb_tcpdump_list, recv_buffer, sizeof(recv_buffer), &data_length);
947 closesocket(sock);
948
949 if (!response) {
950 ws_warning("Failed to get list of available tcpdump interfaces");
951 return EXIT_CODE_GENERIC;
952 }
953 response[data_length] = '\0';
954
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;
959 }
960
961 flags_supported = (strstr(response, "[") != 0) && (strstr(response, "]") != 0);
962
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 gchar *iface = g_match_info_fetch_named(match, "iface");
968 gchar *flags = g_match_info_fetch_named(match, "flags");
969
970 if (!flags_supported || (flags && strstr(flags, "Up"))) {
971 g_snprintf(iface_name, sizeof(iface_name), INTERFACE_ANDROID_TCPDUMP_FORMAT, iface);
972 new_interface(extcap_conf, iface_name, iface, serial_number, "Android tcpdump");
973 }
974 g_free(flags);
975 g_free(iface);
976 }
977 g_match_info_free(match);
978 tok = strtok(NULL, "\n");
979 }
980 g_regex_unref(regex);
981 return 0;
982 }
983
984
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 gssize 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;
1012
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 */
1015
1016 sock = adb_connect(adb_server_ip, adb_server_tcp_port);
1017 if (sock == INVALID_SOCKET)
1018 return EXIT_CODE_INVALID_SOCKET_INTERFACES_LIST;
1019
1020 device_list = adb_send_and_receive(sock, adb_devices, packet, sizeof(packet), &device_length);
1021 closesocket(sock);
1022
1023 if (!device_list) {
1024 ws_warning("Cannot get list of interfaces from devices");
1025
1026 return EXIT_CODE_CANNOT_GET_INTERFACES_LIST;
1027 }
1028
1029 device_list[device_length] = '\0';
1030 pos = (char *) device_list;
1031
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;
1041 }
1042 memcpy(serial_number, prev_pos, result);
1043 serial_number[result] = '\0';
1044
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';
1052 }
1053 }
1054
1055 if (model_name[0] == '\0')
1056 strcpy(model_name, "unknown");
1057
1058 ws_debug("Processing device: \"%s\" <%s>" , serial_number, model_name);
1059
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");
1064 }
1065
1066 sock = adb_connect_transport(adb_server_ip, adb_server_tcp_port, serial_number);
1067 if (sock == INVALID_SOCKET) continue;
1068
1069 response = adb_send_and_read(sock, adb_api_level, helpful_packet, sizeof(helpful_packet), &data_length);
1070 closesocket(sock);
1071
1072 if (!response) {
1073 ws_warning("Error on socket: <%s>", helpful_packet);
1074 continue;
1075 }
1076
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);
1080
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");
1086
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");
1097 }
1098
1099 if (api_level >= 5 && api_level < 17) {
1100 disable_interface = 0;
1101
1102 sock = adb_connect_transport(adb_server_ip, adb_server_tcp_port, serial_number);
1103 if (sock == INVALID_SOCKET) continue;
1104
1105 response = adb_send_and_read(sock, adb_hcidump_version, helpful_packet, sizeof(helpful_packet), &data_length);
1106 closesocket(sock);
1107
1108 if (!response || data_length < 1) {
1109 ws_warning("Error while getting hcidump version by <%s> (%p len=%"G_GSSIZE_FORMAT")",
1110 adb_hcidump_version, (void*)response, 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';
1115
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);
1121 }
1122 }
1123
1124 if (!disable_interface) {
1125 new_interface(extcap_conf, INTERFACE_ANDROID_BLUETOOTH_HCIDUMP, model_name, serial_number, "Android Bluetooth Hcidump");
1126 }
1127 }
1128
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;
1133
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=%"G_GSSIZE_FORMAT")", adb_ps_droid_bluetooth, (void*)response, 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];
1144
1145 memset(pid, 0, sizeof(pid));
1146 response[data_length] = '\0';
1147
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);
1151
1152 result = g_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;
1156 }
1157
1158 sock = adb_connect_transport(adb_server_ip, adb_server_tcp_port, serial_number);
1159 if (sock == INVALID_SOCKET) continue;
1160
1161 response = adb_send_and_read(sock, check_port_buf, helpful_packet, sizeof(helpful_packet), &data_length);
1162 closesocket(sock);
1163
1164 if (!response) {
1165 disable_interface = 1;
1166 } else {
1167 response[data_length] = '\0';
1168
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);
1175 }
1176 }
1177 } else {
1178 disable_interface = 1;
1179 ws_debug("Android Bluetooth application PID for %s is unknown", serial_number);
1180 }
1181 }
1182
1183 if (!disable_interface) {
1184 new_interface(extcap_conf, INTERFACE_ANDROID_BLUETOOTH_EXTERNAL_PARSER, model_name, serial_number, "Android Bluetooth External Parser");
1185 }
1186 }
1187
1188 if (api_level >= 21) {
1189 const char* ps_cmd;
1190 disable_interface = 0;
1191
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;
1200 }
1201 sock = adb_connect_transport(adb_server_ip, adb_server_tcp_port, serial_number);
1202 if (sock == INVALID_SOCKET) continue;
1203
1204 response = adb_send_and_read(sock, ps_cmd, helpful_packet, sizeof(helpful_packet), &data_length);
1205 closesocket(sock);
1206
1207 if (!response || data_length < 1) {
1208 ws_warning("Error while getting Bluetooth application process id by <%s> "
1209 "(%p len=%"G_GSSIZE_FORMAT")", ps_cmd, (void*)response, 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];
1215
1216 memset(pid, 0, sizeof(pid));
1217 response[data_length] = '\0';
1218
1219 if (api_level >= 24)
1220 data_str = response;
1221 else
1222 data_str = strchr(response, '\n');
1223
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);
1226
1227 result = g_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;
1231 }
1232
1233 sock = adb_connect_transport(adb_server_ip, adb_server_tcp_port, serial_number);
1234 if (sock == INVALID_SOCKET) continue;
1235
1236 response = adb_send_and_read(sock, check_port_buf, helpful_packet, sizeof(helpful_packet), &data_length);
1237 closesocket(sock);
1238
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;
1248 }
1249 data_str = strtok(NULL, "\n");
1250 }
1251 if (data_str == NULL) {
1252 disable_interface = 1;
1253 ws_debug("Btsnoop Net Port for %s is unknown", serial_number);
1254 }
1255 }
1256 } else {
1257 disable_interface = 1;
1258 ws_debug("Android Bluetooth application PID for %s is unknown", serial_number);
1259 }
1260 }
1261
1262 if (!disable_interface) {
1263 new_interface(extcap_conf, INTERFACE_ANDROID_BLUETOOTH_BTSNOOP_NET, model_name, serial_number, "Android Bluetooth Btsnoop Net");
1264 }
1265 }
1266 }
1267
1268 return EXIT_CODE_SUCCESS;
1269 }
1270
1271 static int list_config(char *interface) {
1272 int ret = EXIT_CODE_INVALID_INTERFACE;
1273 unsigned inc = 0;
1274
1275 if (!interface) {
1276 ws_warning("No interface specified.");
1277 return EXIT_CODE_NO_INTERFACE_SPECIFIED;
1278 }
1279
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;
1307 }
1308
1309 if (ret != EXIT_CODE_SUCCESS)
1310 ws_warning("Invalid interface: <%s>", interface);
1311 else
1312 extcap_config_debug(&inc);
1313
1314 return ret;
1315 }
1316
1317 /*----------------------------------------------------------------------------*/
1318 /* Android Bluetooth Hcidump */
1319 /*----------------------------------------------------------------------------*/
1320
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 gssize length;
1327 gssize 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 gint64 hex;
1336 char *hex_data;
1337 char *new_hex_data;
1338 own_pcap_bluetooth_h4_header *h4_header;
1339 gint64 raw_length = 0;
1340 gint64 frame_length;
1341 int ms = 0;
1342 struct tm date;
1343 char direction_character;
1344
1345 SET_DATA(h4_header, value_own_pcap_bluetooth_h4_header, packet);
1346
1347 extcap_dumper = extcap_dumper_open(fifo, EXTCAP_ENCAP_BLUETOOTH_H4_WITH_PHDR);
1348
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;
1353
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;
1359 }
1360
1361 while (endless_loop) {
1362 char *i_position;
1363
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
1370 ) {
1371 continue;
1372 }
1373 else if (errno != 0) {
1374 ws_warning("ERROR capture: %s", strerror(errno));
1375 closesocket(sock);
1376 return EXIT_CODE_GENERIC;
1377 }
1378
1379 if (length <= 0) {
1380 ws_warning("Broken socket connection.");
1381 closesocket(sock);
1382 return EXIT_CODE_GENERIC;
1383 }
1384
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;
1389
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;
1394 }
1395
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;
1405 }
1406 memmove(data, i_position, used_buffer_length - (i_position - data));
1407 used_buffer_length = used_buffer_length - (gssize)(i_position - data);
1408 break;
1409 }
1410 }
1411 }
1412
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;
1417
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;
1423 }
1424
1425 used_buffer_length = 0;
1426 while (endless_loop) {
1427 char *i_position;
1428
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
1435 ) {
1436 continue;
1437 }
1438 else if (errno != 0) {
1439 ws_warning("ERROR capture: %s", strerror(errno));
1440 closesocket(sock);
1441 return EXIT_CODE_GENERIC;
1442 }
1443
1444 if (length <= 0) {
1445 ws_warning("Broken socket connection.");
1446 closesocket(sock);
1447 return EXIT_CODE_GENERIC;
1448 }
1449
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;
1457 }
1458
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 - (gssize)(i_position - data);
1464 break;
1465 }
1466 }
1467 }
1468 }
1469
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
1477 ) {
1478 continue;
1479 }
1480 else if (errno != 0) {
1481 ws_warning("ERROR capture: %s", strerror(errno));
1482 closesocket(sock);
1483 return EXIT_CODE_GENERIC;
1484 }
1485
1486 if (length <= 0) {
1487 ws_warning("Broken socket connection.");
1488 closesocket(sock);
1489 return EXIT_CODE_GENERIC;
1490 }
1491
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);
1496
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)) {
1500
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;
1508 }
1509
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;
1516 }
1517
1518 hex_data = new_hex_data;
1519 hex = g_ascii_strtoll(hex_data, &new_hex_data, 16);
1520
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;
1529 }
1530
1531 hex_data = new_hex_data;
1532 hex = g_ascii_strtoll(hex_data, &new_hex_data, 16);
1533
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;
1542 }
1543
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;
1550 }
1551
1552 hex_data = new_hex_data;
1553 hex = g_ascii_strtoll(hex_data, &new_hex_data, 16);
1554 raw_length = hex + 5;
1555
1556 hex_data = new_hex_data;
1557 hex = g_ascii_strtoll(hex_data, &new_hex_data, 16);
1558 raw_length += hex << 8;
1559 }
1560
1561 } else {
1562 ws_warning("bad raw stream");
1563 closesocket(sock);
1564 return EXIT_CODE_GENERIC;
1565 }
1566 } else {
1567 used_buffer_length += length;
1568 break;
1569 }
1570
1571 frame_length = raw_length * 3 + (raw_length / 20) * 4 + ((raw_length % 20) ? 2 : -2) + 29;
1572
1573 if ((used_buffer_length + length) < frame_length) {
1574 used_buffer_length += length;
1575 break;
1576 }
1577
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)) {
1581
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);
1589
1590 new_hex_data = data + 29;
1591 }
1592
1593 captured_length = 0;
1594
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);
1598
1599 packet[sizeof(own_pcap_bluetooth_h4_header) + captured_length] = (char) hex;
1600 captured_length += 1;
1601 }
1602
1603 h4_header->direction = GINT32_TO_BE(direction_character == '>');
1604
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),
1608 ts,
1609 ms * 1000);
1610
1611 memmove(data, data + frame_length, (size_t)(used_buffer_length + length - frame_length));
1612 used_buffer_length = (gssize)(used_buffer_length + length - frame_length);
1613 length = 0;
1614 }
1615 }
1616
1617 closesocket(sock);
1618 return EXIT_CODE_SUCCESS;
1619 }
1620
1621 /*----------------------------------------------------------------------------*/
1622 /* Android Bluetooth External Parser */
1623 /*----------------------------------------------------------------------------*/
1624
1625 #define BLUEDROID_H4_PACKET_TYPE 0
1626 #define BLUEDROID_TIMESTAMP_SIZE 8
1627 #define BLUEDROID_H4_SIZE 1
1628
1629 static const uint64_t BLUEDROID_TIMESTAMP_BASE = G_GUINT64_CONSTANT(0x00dcddb30f2f8000);
1630
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
1635
1636 #define BLUEDROID_DIRECTION_SENT 0
1637 #define BLUEDROID_DIRECTION_RECV 1
1638
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";
1645
1646 sock = adb_connect(adb_server_ip, adb_server_tcp_port);
1647 if (sock == INVALID_SOCKET)
1648 return EXIT_CODE_INVALID_SOCKET_5;
1649
1650 result = g_snprintf(helpful_packet, PACKET_LENGTH, adb_forward_template, (serial_number) ? "host-serial:" : "host", (serial_number) ? serial_number: "", local_tcp_port, server_tcp_port);
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;
1655 }
1656
1657 result = adb_send(sock, helpful_packet);
1658 closesocket(sock);
1659
1660 return result;
1661 }
1662
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 guint8 *payload = packet + sizeof(own_pcap_bluetooth_h4_header);
1673 const char *adb_tcp_bluedroid_external_parser_template = "tcp:%05u";
1674 socklen_t slen;
1675 gssize length;
1676 gssize 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;
1684
1685 SET_DATA(timestamp, value_u64, buffer);
1686 SET_DATA(h4_header, value_own_pcap_bluetooth_h4_header, packet);
1687
1688 extcap_dumper = extcap_dumper_open(fifo, EXTCAP_ENCAP_BLUETOOTH_H4_WITH_PHDR);
1689 serial_number = get_serial_from_interface(interface);
1690
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;
1695 }
1696
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);
1699
1700 if (*bt_local_tcp_port != 0) {
1701 int result;
1702
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);
1706 }
1707
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, &(server.sin_addr.s_addr));
1712
1713 useSndTimeout(sock);
1714
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;
1719 }
1720
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;
1726 }
1727
1728 if (slen != sizeof(client)) {
1729 ws_warning("incorrect length");
1730 closesocket(sock);
1731 return EXIT_CODE_GENERIC;
1732 }
1733
1734 ws_debug("Client port %u", GUINT16_FROM_BE(client.sin_port));
1735 } else {
1736 int result;
1737
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;
1741
1742 result = g_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;
1747 }
1748
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;
1754 }
1755 }
1756
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
1764 ) {
1765 continue;
1766 }
1767 else if (errno != 0) {
1768 ws_warning("ERROR capture: %s", strerror(errno));
1769 closesocket(sock);
1770 return EXIT_CODE_GENERIC;
1771 }
1772
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);
1778
1779 if ((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET) {
1780 ws_warning("%s", strerror(errno));
1781 return EXIT_CODE_GENERIC;
1782 }
1783
1784 server.sin_family = AF_INET;
1785 server.sin_port = GINT16_TO_BE(*bt_local_tcp_port);
1786 ws_inet_pton4(bt_local_ip, &(server.sin_addr.s_addr));
1787
1788 useSndTimeout(sock);
1789
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;
1794 }
1795 } else {
1796 ws_warning("Broken socket connection.");
1797 closesocket(sock);
1798 return EXIT_CODE_GENERIC;
1799 }
1800
1801 continue;
1802 }
1803
1804 used_buffer_length += length;
1805
1806 ws_debug("Received: length=%"G_GSSIZE_FORMAT"", length);
1807
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)) {
1820
1821 ts = GINT64_FROM_BE(*timestamp);
1822
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);
1826
1827 captured_length = (unsigned int)sizeof(own_pcap_bluetooth_h4_header) + payload[3] + 4;
1828
1829 length = sizeof(own_pcap_bluetooth_h4_header) + BLUEDROID_H4_SIZE + 2 + 1 + payload[3];
1830
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);
1834
1835 captured_length = (unsigned int)sizeof(own_pcap_bluetooth_h4_header) + payload[3] + (payload[3 + 1] << 8) + 5;
1836
1837 length = sizeof(own_pcap_bluetooth_h4_header) + BLUEDROID_H4_SIZE + 2 + 2 + payload[3] + (gssize)(payload[3 + 1] << 8);
1838
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);
1842
1843 captured_length = (unsigned int)sizeof(own_pcap_bluetooth_h4_header) + payload[3] + 4;
1844
1845 length = sizeof(own_pcap_bluetooth_h4_header) + BLUEDROID_H4_SIZE + 2 + 1 + payload[3];
1846
1847 break;
1848 case BLUEDROID_H4_PACKET_TYPE_HCI_EVT:
1849 h4_header->direction = GINT32_TO_BE(BLUEDROID_DIRECTION_RECV);
1850
1851 captured_length = (unsigned int)sizeof(own_pcap_bluetooth_h4_header) + payload[2] + 3;
1852
1853 length = sizeof(own_pcap_bluetooth_h4_header) + BLUEDROID_H4_SIZE + 1 + 1 + payload[2];
1854
1855 break;
1856 default:
1857 ws_warning("Invalid stream");
1858 closesocket(sock);
1859 return EXIT_CODE_GENERIC;
1860 }
1861
1862 ws_debug("\t Packet %u: used_buffer_length=%"G_GSSIZE_FORMAT" length=%"G_GSSIZE_FORMAT" captured_length=%i type=0x%02x", id, used_buffer_length, length, captured_length, payload[BLUEDROID_H4_PACKET_TYPE]);
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;
1866
1867 ts -= BLUEDROID_TIMESTAMP_BASE;
1868
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);
1874
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;
1880 }
1881 memmove(buffer, packet + length, used_buffer_length);
1882 }
1883 }
1884
1885 closesocket(sock);
1886 return EXIT_CODE_SUCCESS;
1887 }
1888
1889 /*----------------------------------------------------------------------------*/
1890 /* Android Btsnoop Net */
1891 /*----------------------------------------------------------------------------*/
1892
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 gssize length;
1898 gssize 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 = G_GUINT64_CONSTANT(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;
1912
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));
1919
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;
1925
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;
1931 }
1932
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;
1940 }
1941 used_buffer_length += length;
1942 }
1943 used_buffer_length = 0;
1944
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
1953 ) {
1954 continue;
1955 }
1956 else if (errno != 0) {
1957 ws_warning("ERROR capture: %s", strerror(errno));
1958 closesocket(sock);
1959 return EXIT_CODE_GENERIC;
1960 }
1961
1962 if (length <= 0) {
1963 ws_warning("Broken socket connection.");
1964 closesocket(sock);
1965 return EXIT_CODE_GENERIC;
1966 }
1967
1968 used_buffer_length += length;
1969
1970 while (used_buffer_length >= 24 &&
1971 used_buffer_length >= (int) (24 + GINT32_FROM_BE(*captured_length))) {
1972 gint32 direction;
1973
1974 ts = GINT64_FROM_BE(*timestamp);
1975 ts -= BTSNOOP_TIMESTAMP_BASE;
1976
1977 direction = GINT32_FROM_BE(*flags) & 0x01;
1978 h4_header->direction = GINT32_TO_BE(direction);
1979
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);
1986
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;
1992 }
1993
1994 if (used_buffer_length > 0)
1995 memmove(packet + sizeof(own_pcap_bluetooth_h4_header), payload + GINT32_FROM_BE(*captured_length), used_buffer_length);
1996 }
1997 }
1998
1999 closesocket(sock);
2000 return EXIT_CODE_SUCCESS;
2001 }
2002
2003 /*----------------------------------------------------------------------------*/
2004 /* Android Logcat Text*/
2005 /*----------------------------------------------------------------------------*/
2006
2007
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 gssize 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;
2028
2029 extcap_dumper = extcap_dumper_open(fifo, EXTCAP_ENCAP_WIRESHARK_UPPER_PDU);
2030
2031 exported_pdu_header_protocol_normal.tag = GUINT16_TO_BE(EXP_PDU_TAG_PROTO_NAME);
2032 exported_pdu_header_protocol_normal.length = GUINT16_TO_BE(strlen(wireshark_protocol_logcat_text) + 2);
2033
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;
2038
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;
2053 }
2054
2055 if (logcat_ignore_log_buffer)
2056 logcat_log_buffer = " -T 1";
2057 else
2058 logcat_log_buffer = "";
2059
2060 if (!logcat_custom_parameter)
2061 logcat_custom_parameter = "";
2062
2063 result = g_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;
2068 }
2069
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;
2075 }
2076
2077 protocol_name = wireshark_protocol_logcat_text;
2078 exported_pdu_header_protocol = &exported_pdu_header_protocol_normal;
2079
2080 memcpy(packet, exported_pdu_header_protocol, sizeof(struct exported_pdu_header));
2081 exported_pdu_headers_size += sizeof(struct exported_pdu_header);
2082
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);
2085
2086 packet[exported_pdu_headers_size - 1] = 0;
2087 packet[exported_pdu_headers_size - 2] = 0;
2088
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);
2091
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
2100 ) {
2101 continue;
2102 }
2103 else if (errno != 0) {
2104 ws_warning("ERROR capture: %s", strerror(errno));
2105 closesocket(sock);
2106 return EXIT_CODE_GENERIC;
2107 }
2108
2109 if (length <= 0) {
2110 ws_warning("Broken socket connection. Try reconnect.");
2111 closesocket(sock);
2112 return EXIT_CODE_GENERIC;
2113 }
2114
2115 used_buffer_length += length;
2116
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;
2124
2125 length = (gssize)(pos - packet) + 1;
2126
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);
2138 }
2139
2140 endless_loop = extcap_dumper_dump(extcap_dumper, fifo, packet,
2141 length,
2142 length,
2143 secs, nsecs);
2144
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;
2147 }
2148 }
2149
2150 closesocket(sock);
2151 return EXIT_CODE_SUCCESS;
2152 }
2153
2154 /*----------------------------------------------------------------------------*/
2155 /* Android Logger / Logcat */
2156 /*----------------------------------------------------------------------------*/
2157
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 gssize 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;
2181
2182 extcap_dumper = extcap_dumper_open(fifo, EXTCAP_ENCAP_WIRESHARK_UPPER_PDU);
2183
2184 exported_pdu_header_protocol_events.tag = GUINT16_TO_BE(EXP_PDU_TAG_PROTO_NAME);
2185 exported_pdu_header_protocol_events.length = GUINT16_TO_BE(strlen(wireshark_protocol_logcat_events) + 2);
2186
2187 exported_pdu_header_protocol_normal.tag = GUINT16_TO_BE(EXP_PDU_TAG_PROTO_NAME);
2188 exported_pdu_header_protocol_normal.length = GUINT16_TO_BE(strlen(wireshark_protocol_logcat) + 2);
2189
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;
2194
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;
2200 }
2201
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;
2207 }
2208
2209 if (is_specified_interface(interface, INTERFACE_ANDROID_LOGCAT_EVENTS))
2210 {
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;
2216 }
2217
2218 memcpy(packet, exported_pdu_header_protocol, sizeof(struct exported_pdu_header));
2219 exported_pdu_headers_size += sizeof(struct exported_pdu_header);
2220
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);
2223
2224 packet[exported_pdu_headers_size - 1] = 0;
2225 packet[exported_pdu_headers_size - 2] = 0;
2226
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);
2229
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);
2234
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
2242 ) {
2243 continue;
2244 }
2245 else if (errno != 0) {
2246 ws_warning("ERROR capture: %s", strerror(errno));
2247 closesocket(sock);
2248 return EXIT_CODE_GENERIC;
2249 }
2250
2251 if (length <= 0) {
2252 while (endless_loop) {
2253 ws_warning("Broken socket connection. Try reconnect.");
2254 used_buffer_length = 0;
2255 closesocket(sock);
2256
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;
2260
2261 result = adb_send(sock, adb_command);
2262 if (result) {
2263 ws_warning("WARNING: Error while sending command <%s>", adb_command);
2264 continue;
2265 }
2266
2267 break;
2268 }
2269 }
2270
2271 used_buffer_length += length + exported_pdu_headers_size;
2272
2273 if (*try_header_size != 24)
2274 header_size = 20;
2275 else
2276 header_size = *try_header_size;
2277
2278 length = (*payload_length) + header_size + (gssize)exported_pdu_headers_size;
2279
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);
2285
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;
2289
2290
2291 length = (*payload_length) + header_size + (gssize)exported_pdu_headers_size;
2292
2293 if (*try_header_size != 24)
2294 header_size = 20;
2295 else
2296 header_size = *try_header_size;
2297 }
2298 used_buffer_length -= exported_pdu_headers_size;
2299 }
2300
2301 closesocket(sock);
2302
2303 return EXIT_CODE_SUCCESS;
2304 }
2305
2306
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 const char *adb_server_ip, unsigned short *adb_server_tcp_port) {
2314 static const char *const adb_shell_tcpdump_format = "exec:tcpdump -U -n -s 0 -u -i %s -w - 2>/dev/null";
2315 static const char *const regex_interface = INTERFACE_ANDROID_TCPDUMP "-(?<iface>.*?)-(?<serial>.*)";
2316 struct extcap_dumper extcap_dumper;
2317 static char data[PACKET_LENGTH];
2318 gssize length;
2319 gssize used_buffer_length = 0;
2320 gssize frame_length=0;
2321 socket_handle_t sock;
2322 gint result;
2323 char *iface = NULL;
2324 char *serial_number = NULL;
2325 gboolean nanosecond_timestamps;
2326 gboolean swap_byte_order;
2327 pcap_hdr_t *global_header;
2328 pcaprec_hdr_t p_header;
2329 GRegex *regex = NULL;
2330 GError *err = NULL;
2331 GMatchInfo *match = NULL;
2332 char tcpdump_cmd[80];
2333
2334 regex = g_regex_new(regex_interface, G_REGEX_RAW, (GRegexMatchFlags)0, &err);
2335 if (!regex) {
2336 ws_warning("Failed to compile regex for tcpdump interface");
2337 return EXIT_CODE_GENERIC;
2338 }
2339
2340 g_regex_match(regex, interface, (GRegexMatchFlags)0, &match);
2341 if (!g_match_info_matches(match)) {
2342 ws_warning("Failed to determine iface name and serial number");
2343 g_regex_unref(regex);
2344 return EXIT_CODE_GENERIC;
2345 }
2346
2347 iface = g_match_info_fetch_named(match, "iface");
2348 serial_number = g_match_info_fetch_named(match, "serial");
2349 g_match_info_free(match);
2350 g_regex_unref(regex);
2351
2352 /* First check for the device if it is connected or not */
2353 sock = adb_connect_transport(adb_server_ip, adb_server_tcp_port, serial_number);
2354 g_free(serial_number);
2355 if (sock == INVALID_SOCKET) {
2356 g_free(iface);
2357 return EXIT_CODE_INVALID_SOCKET_11;
2358 }
2359
2360 g_snprintf(tcpdump_cmd, sizeof(tcpdump_cmd), adb_shell_tcpdump_format, iface);
2361 g_free(iface);
2362 result = adb_send(sock, tcpdump_cmd);
2363 if (result) {
2364 ws_warning("Error while setting adb transport");
2365 closesocket(sock);
2366 return EXIT_CODE_GENERIC;
2367 }
2368
2369 while (used_buffer_length < PCAP_GLOBAL_HEADER_LENGTH) {
2370 errno = 0;
2371 length = recv(sock, data + used_buffer_length, (int)(PCAP_GLOBAL_HEADER_LENGTH - used_buffer_length), 0);
2372 if (errno == EAGAIN
2373 #if EWOULDBLOCK != EAGAIN
2374 || errno == EWOULDBLOCK
2375 #endif
2376 ) {
2377 continue;
2378 }
2379 else if (errno != 0) {
2380 ws_warning("ERROR capture: %s", strerror(errno));
2381 closesocket(sock);
2382 return EXIT_CODE_GENERIC;
2383 }
2384
2385 if (length <= 0) {
2386 ws_warning("Broken socket connection.");
2387 closesocket(sock);
2388 return EXIT_CODE_GENERIC;
2389 }
2390
2391 used_buffer_length += length;
2392 }
2393
2394 global_header = (pcap_hdr_t*) data;
2395 switch (global_header->magic_number) {
2396 case 0xa1b2c3d4:
2397 swap_byte_order = FALSE;
2398 nanosecond_timestamps = FALSE;
2399 break;
2400 case 0xd4c3b2a1:
2401 swap_byte_order = TRUE;
2402 nanosecond_timestamps = FALSE;
2403 break;
2404 case 0xa1b23c4d:
2405 swap_byte_order = FALSE;
2406 nanosecond_timestamps = TRUE;
2407 break;
2408 case 0x4d3cb2a1:
2409 swap_byte_order = TRUE;
2410 nanosecond_timestamps = TRUE;
2411 break;
2412 default:
2413 ws_warning("Received incorrect magic");
2414 closesocket(sock);
2415 return EXIT_CODE_GENERIC;
2416 }
2417 int encap = (int)(swap_byte_order ? GUINT32_SWAP_LE_BE(global_header->network) : global_header->network);
2418 #ifndef ANDROIDDUMP_USE_LIBPCAP
2419 encap = wtap_pcap_encap_to_wtap_encap(encap);
2420 #endif
2421 extcap_dumper = extcap_dumper_open(fifo, encap);
2422
2423 used_buffer_length = 0;
2424 while (endless_loop) {
2425 gssize offset = 0;
2426
2427 errno = 0;
2428 length = recv(sock, data + used_buffer_length, (int)(PACKET_LENGTH - used_buffer_length), 0);
2429 if (errno == EAGAIN
2430 #if EWOULDBLOCK != EAGAIN
2431 || errno == EWOULDBLOCK
2432 #endif
2433 ) {
2434 continue;
2435 }
2436 else if (errno != 0) {
2437 ws_warning("ERROR capture: %s", strerror(errno));
2438 closesocket(sock);
2439 return EXIT_CODE_GENERIC;
2440 }
2441
2442 if (length <= 0) {
2443 ws_warning("Broken socket connection.");
2444 closesocket(sock);
2445 return EXIT_CODE_GENERIC;
2446 }
2447
2448 used_buffer_length += length;
2449
2450 while ((used_buffer_length - offset) > PCAP_RECORD_HEADER_LENGTH) {
2451 p_header = *((pcaprec_hdr_t*) (data + offset));
2452 if (swap_byte_order) {
2453 p_header.ts_sec = GUINT32_SWAP_LE_BE(p_header.ts_sec);
2454 p_header.ts_usec = GUINT32_SWAP_LE_BE(p_header.ts_usec);
2455 p_header.incl_len = GUINT32_SWAP_LE_BE(p_header.incl_len);
2456 p_header.orig_len = GUINT32_SWAP_LE_BE(p_header.orig_len);
2457 }
2458 if (!nanosecond_timestamps) {
2459 p_header.ts_usec = p_header.ts_usec * 1000;
2460 }
2461
2462 frame_length = p_header.incl_len + PCAP_RECORD_HEADER_LENGTH;
2463 if ((used_buffer_length - offset) < frame_length) {
2464 break; /* wait for complete packet */
2465 }
2466
2467 /* It was observed that some times tcpdump reports the length of packet as '0' and that leads to the
2468 * ( Warn Error "Less data was read than was expected" while reading )
2469 * So to avoid this error we are checking for length of packet before passing it to dumper.
2470 */
2471 if (p_header.incl_len > 0) {
2472 endless_loop = extcap_dumper_dump(extcap_dumper, fifo, data + offset + PCAP_RECORD_HEADER_LENGTH,
2473 p_header.incl_len, p_header.orig_len, p_header.ts_sec, p_header.ts_usec);
2474 }
2475
2476 offset += frame_length;
2477 }
2478
2479 if (offset < used_buffer_length) {
2480 memmove(data, data + offset, used_buffer_length - offset);
2481 }
2482 used_buffer_length -= offset;
2483 }
2484
2485 closesocket(sock);
2486 return EXIT_CODE_SUCCESS;
2487 }
2488
2489 int main(int argc, char *argv[]) {
2490 char *err_msg;
2491 static const struct report_message_routines androiddummp_report_routines = {
2492 failure_message,
2493 failure_message,
2494 open_failure_message,
2495 read_failure_message,
2496 write_failure_message,
2497 cfile_open_failure_message,
2498 cfile_dump_open_failure_message,
2499 cfile_read_failure_message,
2500 cfile_write_failure_message,
2501 cfile_close_failure_message
2502 };
2503 int ret = EXIT_CODE_GENERIC;
2504 int option_idx = 0;
2505 int result;
2506 const char *adb_server_ip = NULL;
2507 unsigned short *adb_server_tcp_port = NULL;
2508 unsigned int logcat_text = 0;
2509 unsigned int logcat_ignore_log_buffer = 0;
2510 const char *logcat_custom_parameter = NULL;
2511 const char *default_adb_server_ip = "127.0.0.1";
2512 unsigned short default_adb_server_tcp_port = 5037;
2513 unsigned short local_adb_server_tcp_port;
2514 unsigned short local_bt_server_tcp_port;
2515 unsigned short local_bt_local_tcp_port;
2516 unsigned short *bt_server_tcp_port = NULL;
2517 unsigned int bt_forward_socket = 0;
2518 const char *bt_local_ip = NULL;
2519 unsigned short *bt_local_tcp_port = NULL;
2520 unsigned short default_bt_server_tcp_port = 4330;
2521 const char *default_bt_local_ip = "127.0.0.1";
2522 unsigned short default_bt_local_tcp_port = 4330;
2523 extcap_parameters * extcap_conf = NULL;
2524 char *help_url;
2525 char *help_header = NULL;
2526
2527 cmdarg_err_init(androiddump_cmdarg_err, androiddump_cmdarg_err);
2528
2529 /* Initialize log handler early so we can have proper logging during startup. */
2530 extcap_log_init("androiddump");
2531
2532 /*
2533 * Get credential information for later use.
2534 */
2535 init_process_policies();
2536
2537 /*
2538 * Attempt to get the pathname of the directory containing the
2539 * executable file.
2540 */
2541 err_msg = init_progfile_dir(argv[0]);
2542 if (err_msg != NULL) {
2543 ws_warning("Can't get pathname of directory containing the extcap program: %s.",
2544 err_msg);
2545 g_free(err_msg);
2546 }
2547
2548 init_report_message("androiddump", &androiddummp_report_routines);
2549
2550 extcap_conf = g_new0(extcap_parameters, 1);
2551
2552 help_url = data_file_url("androiddump.html");
2553 extcap_base_set_util_info(extcap_conf, argv[0], ANDROIDDUMP_VERSION_MAJOR, ANDROIDDUMP_VERSION_MINOR,
2554 ANDROIDDUMP_VERSION_RELEASE, help_url);
2555 g_free(help_url);
2556
2557 help_header = g_strdup_printf(
2558 " %s --extcap-interfaces [--adb-server-ip=<arg>] [--adb-server-tcp-port=<arg>]\n"
2559 " %s --extcap-interface=INTERFACE --extcap-dlts\n"
2560 " %s --extcap-interface=INTERFACE --extcap-config\n"
2561 " %s --extcap-interface=INTERFACE --fifo=PATH_FILENAME --capture\n"
2562 "\nINTERFACE has the form TYPE-DEVICEID:\n"
2563 "\t""For example: "INTERFACE_ANDROID_BLUETOOTH_BTSNOOP_NET"-W3D7N15C29005648""\n"
2564 "\n"
2565 "\tTYPE is one of:\n"
2566 "\t"INTERFACE_ANDROID_LOGCAT_MAIN"\n"
2567 "\t"INTERFACE_ANDROID_LOGCAT_SYSTEM"\n"
2568 "\t"INTERFACE_ANDROID_LOGCAT_RADIO"\n"
2569 "\t"INTERFACE_ANDROID_LOGCAT_EVENTS"\n"
2570 "\t"INTERFACE_ANDROID_LOGCAT_TEXT_MAIN"\n"
2571 "\t"INTERFACE_ANDROID_LOGCAT_TEXT_SYSTEM"\n"
2572 "\t"INTERFACE_ANDROID_LOGCAT_TEXT_RADIO"\n"
2573 "\t"INTERFACE_ANDROID_LOGCAT_TEXT_EVENTS"\n"
2574 "\t"INTERFACE_ANDROID_LOGCAT_TEXT_CRASH"\n"
2575 "\t"INTERFACE_ANDROID_BLUETOOTH_HCIDUMP"\n"
2576 "\t"INTERFACE_ANDROID_BLUETOOTH_EXTERNAL_PARSER"\n"
2577 "\t"INTERFACE_ANDROID_BLUETOOTH_BTSNOOP_NET"\n"
2578 "\t"INTERFACE_ANDROID_TCPDUMP"\n"
2579 "\n"
2580 "\t""DEVICEID is the identifier of the device provided by Android SDK (see \"adb devices\")\n"
2581 "\t""For example: W3D7N15C29005648""\n",
2582
2583 argv[0], argv[0], argv[0], argv[0]);
2584 extcap_help_add_header(extcap_conf, help_header);
2585 g_free(help_header);
2586
2587 extcap_help_add_option(extcap_conf, "--help", "print this help");
2588 extcap_help_add_option(extcap_conf, "--adb-server-ip <IP>", "the IP address of the ADB server");
2589 extcap_help_add_option(extcap_conf, "--adb-server-tcp-port <port>", "the TCP port of the ADB server");
2590 extcap_help_add_option(extcap_conf, "--logcat-text", "use logcat text format");
2591 extcap_help_add_option(extcap_conf, "--logcat-ignore-log-buffer", "ignore log buffer");
2592 extcap_help_add_option(extcap_conf, "--logcat-custom-options <text>", "use custom logcat parameters");
2593 extcap_help_add_option(extcap_conf, "--bt-server-tcp-port <port>", "bluetooth server TCP port");
2594 extcap_help_add_option(extcap_conf, "--bt-forward-socket <path>", "bluetooth forward socket");
2595 extcap_help_add_option(extcap_conf, "--bt-local-ip <IP>", "the bluetooth local IP");
2596 extcap_help_add_option(extcap_conf, "--bt-local-tcp-port <port>", "the bluetooth local TCP port");
2597
2598 ws_opterr = 0;
2599 ws_optind = 0;
2600
2601 if (argc == 1) {
2602 extcap_help_print(extcap_conf);
2603 ret = EXIT_CODE_SUCCESS;
2604 goto end;
2605 }
2606
2607 while ((result = ws_getopt_long(argc, argv, "", longopts, &option_idx)) != -1) {
2608 switch (result) {
2609
2610 case OPT_VERSION:
2611 extcap_version_print(extcap_conf);
2612 ret = EXIT_CODE_SUCCESS;
2613 goto end;
2614 case OPT_HELP:
2615 extcap_help_print(extcap_conf);
2616 ret = EXIT_CODE_SUCCESS;
2617 goto end;
2618 case OPT_CONFIG_ADB_SERVER_IP:
2619 adb_server_ip = ws_optarg;
2620 break;
2621 case OPT_CONFIG_ADB_SERVER_TCP_PORT:
2622 adb_server_tcp_port = &local_adb_server_tcp_port;
2623 if (!ws_optarg){
2624 ws_warning("Impossible exception. Parameter required argument, but there is no it right now.");
2625 goto end;
2626 }
2627 if (!ws_strtou16(ws_optarg, NULL, adb_server_tcp_port)) {
2628 ws_warning("Invalid adb server TCP port: %s", ws_optarg);
2629 goto end;
2630 }
2631 break;
2632 case OPT_CONFIG_LOGCAT_TEXT:
2633 if (ws_optarg && !*ws_optarg)
2634 logcat_text = TRUE;
2635 else
2636 logcat_text = (g_ascii_strncasecmp(ws_optarg, "TRUE", 4) == 0);
2637 break;
2638 case OPT_CONFIG_LOGCAT_IGNORE_LOG_BUFFER:
2639 if (ws_optarg == NULL || (ws_optarg && !*ws_optarg))
2640 logcat_ignore_log_buffer = TRUE;
2641 else
2642 logcat_ignore_log_buffer = (g_ascii_strncasecmp(ws_optarg, "TRUE", 4) == 0);
2643 break;
2644 case OPT_CONFIG_LOGCAT_CUSTOM_OPTIONS:
2645 if (ws_optarg == NULL || (ws_optarg && *ws_optarg == '\0')) {
2646 logcat_custom_parameter = NULL;
2647 break;
2648 }
2649
2650 if (g_regex_match_simple("(^|\\s)-[bBcDfgLnpPrv]", ws_optarg, G_REGEX_RAW, (GRegexMatchFlags)0)) {
2651 ws_error("Found prohibited option in logcat-custom-options");
2652 return EXIT_CODE_GENERIC;
2653 }
2654
2655 logcat_custom_parameter = ws_optarg;
2656
2657 break;
2658 case OPT_CONFIG_BT_SERVER_TCP_PORT:
2659 bt_server_tcp_port = &local_bt_server_tcp_port;
2660 if (!ws_optarg){
2661 ws_warning("Impossible exception. Parameter required argument, but there is no it right now.");
2662 goto end;
2663 }
2664 if (!ws_strtou16(ws_optarg, NULL, bt_server_tcp_port)) {
2665 ws_warning("Invalid bluetooth server TCP port: %s", ws_optarg);
2666 goto end;
2667 }
2668 break;
2669 case OPT_CONFIG_BT_FORWARD_SOCKET:
2670 bt_forward_socket = (g_ascii_strncasecmp(ws_optarg, "TRUE", 4) == 0);
2671 break;
2672 case OPT_CONFIG_BT_LOCAL_IP:
2673 bt_local_ip = ws_optarg;
2674 break;
2675 case OPT_CONFIG_BT_LOCAL_TCP_PORT:
2676 bt_local_tcp_port = &local_bt_local_tcp_port;
2677 if (!ws_optarg){
2678 ws_warning("Impossible exception. Parameter required argument, but there is no it right now.");
2679 goto end;
2680 }
2681 if (!ws_strtou16(ws_optarg, NULL, bt_local_tcp_port)) {
2682 ws_warning("Invalid bluetooth local tcp port: %s", ws_optarg);
2683 goto end;
2684 }
2685 break;
2686 default:
2687 if (!extcap_base_parse_options(extcap_conf, result - EXTCAP_OPT_LIST_INTERFACES, ws_optarg))
2688 {
2689 ws_warning("Invalid argument <%s>. Try --help.\n", argv[ws_optind - 1]);
2690 goto end;
2691 }
2692 }
2693 }
2694
2695 if (!adb_server_ip)
2696 adb_server_ip = default_adb_server_ip;
2697
2698 if (!adb_server_tcp_port)
2699 adb_server_tcp_port = &default_adb_server_tcp_port;
2700
2701 if (!bt_server_tcp_port)
2702 bt_server_tcp_port = &default_bt_server_tcp_port;
2703
2704 if (!bt_local_ip)
2705 bt_local_ip = default_bt_local_ip;
2706
2707 if (!bt_local_tcp_port)
2708 bt_local_tcp_port = &default_bt_local_tcp_port;
2709
2710 err_msg = ws_init_sockets();
2711 if (err_msg != NULL) {
2712 ws_warning("ERROR: %s", err_msg);
2713 g_free(err_msg);
2714 ws_warning("%s", please_report_bug());
2715 goto end;
2716 }
2717
2718 extcap_cmdline_debug(argv, argc);
2719
2720 if (extcap_conf->do_list_interfaces)
2721 register_interfaces(extcap_conf, adb_server_ip, adb_server_tcp_port);
2722
2723 /* NOTE:
2724 * extcap implementation calls androiddump --extcap-dlts for each interface.
2725 * The only way to know whether an interface exists or not is to go through the
2726 * whole process of listing all interfaces (i.e. calling register_interfaces
2727 * function). Since being a system resource heavy operation and repeated for
2728 * each interface instead register a fake interface to be returned for dlt
2729 * listing only purpose
2730 */
2731 if (extcap_conf->do_list_dlts) {
2732 new_fake_interface_for_list_dlts(extcap_conf, extcap_conf->interface);
2733 }
2734
2735 if (extcap_base_handle_interface(extcap_conf)) {
2736 ret = EXIT_CODE_SUCCESS;
2737 goto end;
2738 }
2739
2740 if (extcap_conf->show_config) {
2741 ret = list_config(extcap_conf->interface);
2742 goto end;
2743 }
2744
2745 if (extcap_conf->capture) {
2746 if (extcap_conf->interface && is_logcat_interface(extcap_conf->interface))
2747 if (logcat_text)
2748 ret = capture_android_logcat_text(extcap_conf->interface,
2749 extcap_conf->fifo, adb_server_ip, adb_server_tcp_port,
2750 logcat_ignore_log_buffer, logcat_custom_parameter);
2751 else
2752 ret = capture_android_logcat(extcap_conf->interface,
2753 extcap_conf->fifo, adb_server_ip, adb_server_tcp_port);
2754 else if (extcap_conf->interface && is_logcat_text_interface(extcap_conf->interface))
2755 ret = capture_android_logcat_text(extcap_conf->interface,
2756 extcap_conf->fifo, adb_server_ip, adb_server_tcp_port,
2757 logcat_ignore_log_buffer, logcat_custom_parameter);
2758 else if (extcap_conf->interface && is_specified_interface(extcap_conf->interface, INTERFACE_ANDROID_BLUETOOTH_HCIDUMP))
2759 ret = capture_android_bluetooth_hcidump(extcap_conf->interface, extcap_conf->fifo, adb_server_ip, adb_server_tcp_port);
2760 else if (extcap_conf->interface && is_specified_interface(extcap_conf->interface, INTERFACE_ANDROID_BLUETOOTH_EXTERNAL_PARSER))
2761 ret = capture_android_bluetooth_external_parser(extcap_conf->interface, extcap_conf->fifo, adb_server_ip, adb_server_tcp_port,
2762 bt_server_tcp_port, bt_forward_socket, bt_local_ip, bt_local_tcp_port);
2763 else if (extcap_conf->interface && (is_specified_interface(extcap_conf->interface, INTERFACE_ANDROID_BLUETOOTH_BTSNOOP_NET)))
2764 ret = capture_android_bluetooth_btsnoop_net(extcap_conf->interface, extcap_conf->fifo, adb_server_ip, adb_server_tcp_port);
2765 else if (extcap_conf->interface && (is_specified_interface(extcap_conf->interface,INTERFACE_ANDROID_TCPDUMP)))
2766 ret = capture_android_tcpdump(extcap_conf->interface, extcap_conf->fifo, adb_server_ip, adb_server_tcp_port);
2767
2768 goto end;
2769 }
2770
2771 /* no action was given, assume success */
2772 ret = EXIT_CODE_SUCCESS;
2773
2774 end:
2775 /* clean up stuff */
2776 extcap_base_cleanup(&extcap_conf);
2777 #ifndef ANDROIDDUMP_USE_LIBPCAP
2778 wtap_cleanup();
2779 #endif
2780
2781 return ret;
2782 }
2783
2784 /*
2785 * Editor modelines - https://www.wireshark.org/tools/modelines.html
2786 *
2787 * Local variables:
2788 * c-basic-offset: 4
2789 * tab-width: 8
2790 * indent-tabs-mode: nil
2791 * End:
2792 *
2793 * vi: set shiftwidth=4 tabstop=8 expandtab:
2794 * :indentSize=4:tabSize=8:noTabs=true:
2795 */
2796