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, &params, &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