2969a33cf7c6b5d5f7373f0721e17e04317b4e29
[metze/wireshark/wip.git] / extcap / androiddump.c
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+
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/cmdarg_err.h>
24 #include <wsutil/inet_addr.h>
25
26 #include "ui/failure_message.h"
27
28 #ifdef HAVE_NETINET_IN_H
29 #    include <netinet/in.h>
30 #endif
31
32 #ifdef HAVE_UNISTD_H
33     #include <unistd.h>
34 #endif
35
36 #ifdef HAVE_SYS_SOCKET_H
37     #include <sys/socket.h>
38 #endif
39
40 #ifdef HAVE_ARPA_INET_H
41     #include <arpa/inet.h>
42 #endif
43
44 #ifdef HAVE_SYS_TIME_H
45     #include <sys/time.h>
46 #endif
47
48 /* Configuration options */
49 /* #define ANDROIDDUMP_USE_LIBPCAP */
50
51 #define PCAP_GLOBAL_HEADER_LENGTH              24
52 #define PCAP_RECORD_HEADER_LENGTH              16
53
54 #ifdef ANDROIDDUMP_USE_LIBPCAP
55     #include <wsutil/wspcap.h>
56     #include <pcap-bpf.h>
57     #include <pcap/bluetooth.h>
58
59     #ifndef DLT_BLUETOOTH_H4_WITH_PHDR
60     #define DLT_BLUETOOTH_H4_WITH_PHDR 201
61     #endif
62
63     #ifndef DLT_WIRESHARK_UPPER_PDU
64     #define DLT_WIRESHARK_UPPER_PDU  252
65     #endif
66
67     #ifndef PCAP_TSTAMP_PRECISION_MICRO
68     #define PCAP_TSTAMP_PRECISION_MICRO 0
69     #endif
70
71     #ifndef PCAP_TSTAMP_PRECISION_NANO
72     #define PCAP_TSTAMP_PRECISION_NANO 1
73     #endif
74 #else
75     #include "wiretap/wtap.h"
76 #endif
77
78 #ifdef ANDROIDDUMP_USE_LIBPCAP
79     #define EXTCAP_ENCAP_BLUETOOTH_H4_WITH_PHDR DLT_BLUETOOTH_H4_WITH_PHDR
80     #define EXTCAP_ENCAP_WIRESHARK_UPPER_PDU    DLT_WIRESHARK_UPPER_PDU
81     #define EXTCAP_ENCAP_ETHERNET               DLT_EN10MB
82     #define EXTCAP_ENCAP_LINUX_SLL              DLT_LINUX_SLL
83     #define EXTCAP_ENCAP_IEEE802_11_RADIO       DLT_IEEE802_11_RADIO
84     #define EXTCAP_ENCAP_NETLINK                DLT_NETLINK
85 #else
86     #define EXTCAP_ENCAP_BLUETOOTH_H4_WITH_PHDR WTAP_ENCAP_BLUETOOTH_H4_WITH_PHDR
87     #define EXTCAP_ENCAP_WIRESHARK_UPPER_PDU    WTAP_ENCAP_WIRESHARK_UPPER_PDU
88     #define EXTCAP_ENCAP_ETHERNET               WTAP_ENCAP_ETHERNET
89     #define EXTCAP_ENCAP_LINUX_SLL              WTAP_ENCAP_SLL
90     #define EXTCAP_ENCAP_IEEE802_11_RADIO       WTAP_ENCAP_IEEE_802_11_RADIOTAP
91     #define EXTCAP_ENCAP_NETLINK                WTAP_ENCAP_NETLINK
92 #endif
93
94 #define WIRESHARK_UPPER_PDU_TAG_DISSECTOR_NAME  0x000C
95
96 #define INTERFACE_ANDROID_LOGCAT_MAIN                   "android-logcat-main"
97 #define INTERFACE_ANDROID_LOGCAT_SYSTEM                 "android-logcat-system"
98 #define INTERFACE_ANDROID_LOGCAT_RADIO                  "android-logcat-radio"
99 #define INTERFACE_ANDROID_LOGCAT_EVENTS                 "android-logcat-events"
100 #define INTERFACE_ANDROID_LOGCAT_TEXT_MAIN              "android-logcat-text-main"
101 #define INTERFACE_ANDROID_LOGCAT_TEXT_SYSTEM            "android-logcat-text-system"
102 #define INTERFACE_ANDROID_LOGCAT_TEXT_RADIO             "android-logcat-text-radio"
103 #define INTERFACE_ANDROID_LOGCAT_TEXT_EVENTS            "android-logcat-text-events"
104 #define INTERFACE_ANDROID_LOGCAT_TEXT_CRASH             "android-logcat-text-crash"
105 #define INTERFACE_ANDROID_BLUETOOTH_HCIDUMP             "android-bluetooth-hcidump"
106 #define INTERFACE_ANDROID_BLUETOOTH_EXTERNAL_PARSER     "android-bluetooth-external-parser"
107 #define INTERFACE_ANDROID_BLUETOOTH_BTSNOOP_NET         "android-bluetooth-btsnoop-net"
108 #define INTERFACE_ANDROID_TCPDUMP                       "android-tcpdump"
109 #define INTERFACE_ANDROID_TCPDUMP_FORMAT                INTERFACE_ANDROID_TCPDUMP "-%s"
110 #define INTERFACE_ANDROID_TCPDUMP_SERIAL_FORMAT         INTERFACE_ANDROID_TCPDUMP_FORMAT "-%s"
111
112 #define ANDROIDDUMP_VERSION_MAJOR    "1"
113 #define ANDROIDDUMP_VERSION_MINOR    "1"
114 #define ANDROIDDUMP_VERSION_RELEASE  "0"
115
116 #define SERIAL_NUMBER_LENGTH_MAX  512
117 #define MODEL_NAME_LENGTH_MAX      64
118
119 #define PACKET_LENGTH 65535
120
121 #define SOCKET_RW_TIMEOUT_MS         2000
122 #define SOCKET_CONNECT_TIMEOUT_TRIES   10
123 #define SOCKET_CONNECT_DELAY_US      1000 /* (1000us = 1ms) * SOCKET_CONNECT_TIMEOUT_TRIES (10) = 10ms worst-case  */
124
125 #define ADB_HEX4_FORMAT "%04zx"
126 #define ADB_HEX4_LEN    4
127
128 enum exit_code {
129     EXIT_CODE_SUCCESS = 0,
130     EXIT_CODE_CANNOT_GET_INTERFACES_LIST = 1,
131     EXIT_CODE_UNKNOWN_ENCAPSULATION_WIRETAP,
132     EXIT_CODE_UNKNOWN_ENCAPSULATION_LIBPCAP,
133     EXIT_CODE_CANNOT_SAVE_WIRETAP_DUMP,
134     EXIT_CODE_CANNOT_SAVE_LIBPCAP_DUMP,
135     EXIT_CODE_NO_INTERFACE_SPECIFIED,
136     EXIT_CODE_INVALID_INTERFACE,
137     EXIT_CODE_BAD_SIZE_OF_ASSEMBLED_ADB_PACKET_1,
138     EXIT_CODE_BAD_SIZE_OF_ASSEMBLED_ADB_PACKET_2,
139     EXIT_CODE_BAD_SIZE_OF_ASSEMBLED_ADB_PACKET_3,
140     EXIT_CODE_BAD_SIZE_OF_ASSEMBLED_ADB_PACKET_4,
141     EXIT_CODE_BAD_SIZE_OF_ASSEMBLED_ADB_PACKET_5,
142     EXIT_CODE_BAD_SIZE_OF_ASSEMBLED_ADB_PACKET_6,
143     EXIT_CODE_BAD_SIZE_OF_ASSEMBLED_ADB_PACKET_7,
144     EXIT_CODE_BAD_SIZE_OF_ASSEMBLED_ADB_PACKET_8,
145     EXIT_CODE_BAD_SIZE_OF_ASSEMBLED_ADB_PACKET_9,
146     EXIT_CODE_BAD_SIZE_OF_ASSEMBLED_ADB_PACKET_10,
147     EXIT_CODE_BAD_SIZE_OF_ASSEMBLED_ADB_PACKET_11,
148     EXIT_CODE_BAD_SIZE_OF_ASSEMBLED_ADB_PACKET_12,
149     EXIT_CODE_BAD_SIZE_OF_ASSEMBLED_ADB_PACKET_13,
150     EXIT_CODE_BAD_SIZE_OF_ASSEMBLED_ADB_PACKET_14,
151     EXIT_CODE_BAD_SIZE_OF_ASSEMBLED_ADB_PACKET_15,
152     EXIT_CODE_BAD_SIZE_OF_ASSEMBLED_ADB_PACKET_16,
153     EXIT_CODE_BAD_SIZE_OF_ASSEMBLED_ADB_PACKET_17,
154     EXIT_CODE_BAD_SIZE_OF_ASSEMBLED_ADB_PACKET_18,
155     EXIT_CODE_BAD_SIZE_OF_ASSEMBLED_ADB_PACKET_19,
156     EXIT_CODE_BAD_SIZE_OF_ASSEMBLED_ADB_PACKET_20,
157     EXIT_CODE_ERROR_WHILE_SENDING_ADB_PACKET_1,
158     EXIT_CODE_ERROR_WHILE_SENDING_ADB_PACKET_2,
159     EXIT_CODE_ERROR_WHILE_SENDING_ADB_PACKET_3,
160     EXIT_CODE_ERROR_WHILE_SENDING_ADB_PACKET_4,
161     EXIT_CODE_ERROR_WHILE_RECEIVING_ADB_PACKET_STATUS,
162     EXIT_CODE_ERROR_WHILE_RECEIVING_ADB_PACKET_DATA,
163     EXIT_CODE_INVALID_SOCKET_INTERFACES_LIST,
164     EXIT_CODE_INVALID_SOCKET_1,
165     EXIT_CODE_INVALID_SOCKET_2,
166     EXIT_CODE_INVALID_SOCKET_3,
167     EXIT_CODE_INVALID_SOCKET_4,
168     EXIT_CODE_INVALID_SOCKET_5,
169     EXIT_CODE_INVALID_SOCKET_6,
170     EXIT_CODE_INVALID_SOCKET_7,
171     EXIT_CODE_INVALID_SOCKET_8,
172     EXIT_CODE_INVALID_SOCKET_9,
173     EXIT_CODE_INVALID_SOCKET_10,
174     EXIT_CODE_INVALID_SOCKET_11,
175     EXIT_CODE_INVALID_SOCKET_12,
176     EXIT_CODE_GENERIC = -1
177 };
178
179 enum {
180     EXTCAP_BASE_OPTIONS_ENUM,
181     OPT_HELP,
182     OPT_VERSION,
183     OPT_CONFIG_ADB_SERVER_IP,
184     OPT_CONFIG_ADB_SERVER_TCP_PORT,
185     OPT_CONFIG_LOGCAT_TEXT,
186     OPT_CONFIG_LOGCAT_IGNORE_LOG_BUFFER,
187     OPT_CONFIG_LOGCAT_CUSTOM_OPTIONS,
188     OPT_CONFIG_BT_SERVER_TCP_PORT,
189     OPT_CONFIG_BT_FORWARD_SOCKET,
190     OPT_CONFIG_BT_LOCAL_IP,
191     OPT_CONFIG_BT_LOCAL_TCP_PORT
192 };
193
194 static struct option longopts[] = {
195     EXTCAP_BASE_OPTIONS,
196     { "help",                     no_argument,       NULL, OPT_HELP},
197     { "version",                  no_argument,       NULL, OPT_VERSION},
198     { "adb-server-ip",            required_argument, NULL, OPT_CONFIG_ADB_SERVER_IP},
199     { "adb-server-tcp-port",      required_argument, NULL, OPT_CONFIG_ADB_SERVER_TCP_PORT},
200     { "logcat-text",              optional_argument, NULL, OPT_CONFIG_LOGCAT_TEXT},
201     { "logcat-ignore-log-buffer", optional_argument, NULL, OPT_CONFIG_LOGCAT_IGNORE_LOG_BUFFER},
202     { "logcat-custom-options",    required_argument, NULL, OPT_CONFIG_LOGCAT_CUSTOM_OPTIONS},
203     { "bt-server-tcp-port",       required_argument, NULL, OPT_CONFIG_BT_SERVER_TCP_PORT},
204     { "bt-forward-socket",        required_argument, NULL, OPT_CONFIG_BT_FORWARD_SOCKET},
205     { "bt-local-ip",              required_argument, NULL, OPT_CONFIG_BT_LOCAL_IP},
206     { "bt-local-tcp-port",        required_argument, NULL, OPT_CONFIG_BT_LOCAL_TCP_PORT},
207     { 0, 0, 0, 0 }
208 };
209
210 struct interface_t {
211     const char          *display_name;
212     const char          *interface_name;
213     struct interface_t  *next;
214 };
215
216 struct exported_pdu_header {
217     uint16_t  tag;
218     uint16_t  length;
219 /*  unsigned char value[0]; */
220 };
221
222
223 typedef struct _own_pcap_bluetooth_h4_header {
224     uint32_t direction;
225 } own_pcap_bluetooth_h4_header;
226
227 typedef struct pcaprec_hdr_s {
228         guint32 ts_sec;         /* timestamp seconds */
229         guint32 ts_usec;        /* timestamp microseconds */
230         guint32 incl_len;       /* number of octets of packet saved in file */
231         guint32 orig_len;       /* actual length of packet */
232 } pcaprec_hdr_t;
233
234 /* This fix compilator warning like "warning: cast from 'char *' to 'uint32_t *' (aka 'unsigned int *') increases required alignment from 1 to 4 " */
235 typedef union {
236     char      *value_char;
237     uint8_t   *value_u8;
238     uint16_t  *value_u16;
239     uint32_t  *value_u32;
240     uint64_t  *value_u64;
241     int8_t    *value_i8;
242     int16_t   *value_i16;
243     int32_t   *value_i32;
244     int64_t   *value_i64;
245     own_pcap_bluetooth_h4_header  *value_own_pcap_bluetooth_h4_header;
246 } data_aligned_t;
247
248 #define SET_DATA(dest, type, src) \
249     { \
250         data_aligned_t data_aligned; \
251             \
252         data_aligned.value_char = src; \
253         dest = data_aligned.type; \
254     }
255
256 struct extcap_dumper {
257     int encap;
258     union  {
259 #ifdef ANDROIDDUMP_USE_LIBPCAP
260         pcap_dumper_t  *pcap;
261 #else
262         wtap_dumper    *wtap;
263 #endif
264     } dumper;
265 };
266
267 /* Globals */
268 static int endless_loop = 1;
269
270 /* Functions */
271 static inline int is_specified_interface(const char *interface, const char *interface_prefix) {
272     return !strncmp(interface, interface_prefix, strlen(interface_prefix));
273 }
274
275 static gboolean is_logcat_interface(const char *interface) {
276     return is_specified_interface(interface, INTERFACE_ANDROID_LOGCAT_MAIN) ||
277            is_specified_interface(interface, INTERFACE_ANDROID_LOGCAT_SYSTEM) ||
278            is_specified_interface(interface, INTERFACE_ANDROID_LOGCAT_RADIO) ||
279            is_specified_interface(interface, INTERFACE_ANDROID_LOGCAT_EVENTS);
280 }
281
282 static gboolean is_logcat_text_interface(const char *interface) {
283     return is_specified_interface(interface, INTERFACE_ANDROID_LOGCAT_TEXT_MAIN) ||
284            is_specified_interface(interface, INTERFACE_ANDROID_LOGCAT_TEXT_SYSTEM) ||
285            is_specified_interface(interface, INTERFACE_ANDROID_LOGCAT_TEXT_RADIO) ||
286            is_specified_interface(interface, INTERFACE_ANDROID_LOGCAT_TEXT_EVENTS) ||
287            is_specified_interface(interface, INTERFACE_ANDROID_LOGCAT_TEXT_CRASH);
288 }
289
290 static char* get_serial_from_interface(char *interface)
291 {
292     static const char* const iface_prefix[] = {
293         INTERFACE_ANDROID_LOGCAT_MAIN,
294         INTERFACE_ANDROID_LOGCAT_SYSTEM,
295         INTERFACE_ANDROID_LOGCAT_RADIO,
296         INTERFACE_ANDROID_LOGCAT_EVENTS,
297         INTERFACE_ANDROID_LOGCAT_TEXT_MAIN,
298         INTERFACE_ANDROID_LOGCAT_TEXT_SYSTEM,
299         INTERFACE_ANDROID_LOGCAT_TEXT_RADIO,
300         INTERFACE_ANDROID_LOGCAT_TEXT_EVENTS,
301         INTERFACE_ANDROID_LOGCAT_TEXT_CRASH,
302         INTERFACE_ANDROID_BLUETOOTH_HCIDUMP,
303         INTERFACE_ANDROID_BLUETOOTH_EXTERNAL_PARSER,
304         INTERFACE_ANDROID_BLUETOOTH_BTSNOOP_NET,
305         NULL
306     };
307     int i;
308     const char* curr = NULL;
309     for (i = 0; (curr = iface_prefix[i]); i++) {
310         if (is_specified_interface(interface, curr) &&
311                 strlen(interface) > strlen(curr) + 1) {
312             return interface + strlen(curr) + 1;
313         }
314     }
315     return NULL;
316 }
317
318 static const char* interface_to_logbuf(char* interface)
319 {
320     const char *const adb_log_main   = "log:main";
321     const char *const adb_log_system = "log:system";
322     const char *const adb_log_radio  = "log:radio";
323     const char *const adb_log_events = "log:events";
324     const char *logbuf = NULL;
325
326     if (is_specified_interface(interface, INTERFACE_ANDROID_LOGCAT_MAIN))
327         logbuf = adb_log_main;
328     else if (is_specified_interface(interface, INTERFACE_ANDROID_LOGCAT_SYSTEM))
329         logbuf = adb_log_system;
330     else if (is_specified_interface(interface, INTERFACE_ANDROID_LOGCAT_RADIO))
331         logbuf = adb_log_radio;
332     else if (is_specified_interface(interface, INTERFACE_ANDROID_LOGCAT_EVENTS))
333         logbuf = adb_log_events;
334     return logbuf;
335 }
336
337 /*
338  * General errors and warnings are reported through g_warning() in
339  * androiddump.
340  *
341  * Unfortunately, g_warning() may be a macro, so we do it by calling
342  * g_logv() with the appropriate arguments.
343  */
344 static void
345 failure_warning_message(const char *msg_format, va_list ap)
346 {
347     g_logv(G_LOG_DOMAIN, G_LOG_LEVEL_WARNING, msg_format, ap);
348 }
349
350 static void useSndTimeout(socket_handle_t  sock) {
351     int res;
352 #ifdef _WIN32
353     const DWORD socket_timeout = SOCKET_RW_TIMEOUT_MS;
354
355     res = setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, (const char *) &socket_timeout, (socklen_t)sizeof(socket_timeout));
356 #else
357     const struct timeval socket_timeout = {
358         .tv_sec = SOCKET_RW_TIMEOUT_MS / 1000,
359         .tv_usec = (SOCKET_RW_TIMEOUT_MS % 1000) * 1000
360     };
361
362     res = setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, &socket_timeout, (socklen_t)sizeof(socket_timeout));
363 #endif
364     if (res != 0)
365         g_debug("Can't set socket timeout, using default");
366 }
367
368 static void useNonBlockingConnectTimeout(socket_handle_t  sock) {
369     int res_snd;
370     int res_rcv;
371 #ifdef _WIN32
372     const DWORD socket_timeout = SOCKET_RW_TIMEOUT_MS;
373     unsigned long non_blocking = 1;
374
375     res_snd = setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, (const char *) &socket_timeout, sizeof(socket_timeout));
376     res_rcv = setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (const char *) &socket_timeout, sizeof(socket_timeout));
377
378     /* set socket to non-blocking */
379     ioctlsocket(sock, FIONBIO, &non_blocking);
380 #else
381     const struct timeval socket_timeout = {
382         .tv_sec = SOCKET_RW_TIMEOUT_MS / 1000,
383         .tv_usec = (SOCKET_RW_TIMEOUT_MS % 1000) * 1000
384     };
385
386     res_snd = setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, &socket_timeout, sizeof(socket_timeout));
387     res_rcv = setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &socket_timeout, sizeof(socket_timeout));
388 #endif
389     if (res_snd != 0)
390         g_debug("Can't set socket timeout, using default");
391     if (res_rcv != 0)
392         g_debug("Can't set socket timeout, using default");
393 }
394
395 static void useNormalConnectTimeout(socket_handle_t  sock) {
396     int res_rcv;
397 #ifdef _WIN32
398     const DWORD socket_timeout = 0;
399     unsigned long non_blocking = 0;
400
401     res_rcv = setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (const char *) &socket_timeout, sizeof(socket_timeout));
402     ioctlsocket(sock, FIONBIO, &non_blocking);
403 #else
404     const struct timeval socket_timeout = {
405         .tv_sec = SOCKET_RW_TIMEOUT_MS / 1000,
406         .tv_usec = (SOCKET_RW_TIMEOUT_MS % 1000) * 1000
407     };
408
409     res_rcv = setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &socket_timeout, sizeof(socket_timeout));
410 #endif
411     if (res_rcv != 0)
412         g_debug("Can't set socket timeout, using default");
413 }
414
415 static struct extcap_dumper extcap_dumper_open(char *fifo, int encap) {
416     struct extcap_dumper extcap_dumper;
417
418 #ifdef ANDROIDDUMP_USE_LIBPCAP
419     pcap_t  *pcap;
420
421     pcap = pcap_open_dead_with_tstamp_precision(encap, PACKET_LENGTH, PCAP_TSTAMP_PRECISION_NANO);
422     extcap_dumper.dumper.pcap = pcap_dump_open(pcap, fifo);
423     if (!extcap_dumper.dumper.pcap) {
424         g_warning("Can't open %s for saving packets: %s", pcap_geterr(pcap));
425         pcap_close(pcap);
426         exit(EXIT_CODE_CANNOT_SAVE_LIBPCAP_DUMP);
427     }
428     extcap_dumper.encap = encap;
429     if (pcap_dump_flush(extcap_dumper.dumper.pcap) == -1) {
430         g_warning("Write to %s failed: %s", g_strerror(errno));
431     }
432 #else
433     int err = 0;
434
435     wtap_init(FALSE);
436
437     extcap_dumper.dumper.wtap = wtap_dump_open(fifo, WTAP_FILE_TYPE_SUBTYPE_PCAP_NSEC, encap, PACKET_LENGTH, FALSE, &err);
438     if (!extcap_dumper.dumper.wtap) {
439         cfile_dump_open_failure_message("androiddump", fifo, err, WTAP_FILE_TYPE_SUBTYPE_PCAP_NSEC);
440         exit(EXIT_CODE_CANNOT_SAVE_WIRETAP_DUMP);
441     }
442     extcap_dumper.encap = encap;
443     wtap_dump_flush(extcap_dumper.dumper.wtap);
444 #endif
445
446     return extcap_dumper;
447 }
448
449 static gboolean extcap_dumper_dump(struct extcap_dumper extcap_dumper,
450         char *fifo, char *buffer,
451         gssize captured_length, gssize reported_length,
452         time_t seconds, int nanoseconds) {
453 #ifdef ANDROIDDUMP_USE_LIBPCAP
454     struct pcap_pkthdr  pcap_header;
455
456     pcap_header.caplen = (bpf_u_int32) captured_length;
457     pcap_header.len = (bpf_u_int32) reported_length;
458     pcap_header.ts.tv_sec = seconds;
459     pcap_header.ts.tv_usec = nanoseconds / 1000;
460
461     pcap_dump((u_char *) extcap_dumper.dumper.pcap, &pcap_header, buffer);
462     if (pcap_dump_flush(extcap_dumper.dumper.pcap) == -1) {
463         g_warning("Write to %s failed: %s", g_strerror(errno));
464     }
465 #else
466     int                 err = 0;
467     char               *err_info;
468     struct wtap_pkthdr  hdr;
469
470     hdr.presence_flags = WTAP_HAS_TS;
471     hdr.caplen = (guint32) captured_length;
472     hdr.len = (guint32) reported_length;
473
474     hdr.ts.secs = seconds;
475     hdr.ts.nsecs = (int) nanoseconds;
476
477     hdr.opt_comment = 0;
478     hdr.opt_comment = NULL;
479     hdr.drop_count = 0;
480     hdr.pack_flags = 0;
481     hdr.rec_type = REC_TYPE_PACKET;
482
483 /*  NOTE: Try to handle pseudoheaders manually */
484     if (extcap_dumper.encap == EXTCAP_ENCAP_BLUETOOTH_H4_WITH_PHDR) {
485         uint32_t *direction;
486
487         SET_DATA(direction, value_u32, buffer)
488
489         hdr.pseudo_header.bthci.sent = GINT32_FROM_BE(*direction) ? 0 : 1;
490
491         hdr.len -= (guint32)sizeof(own_pcap_bluetooth_h4_header);
492         hdr.caplen -= (guint32)sizeof(own_pcap_bluetooth_h4_header);
493
494         buffer += sizeof(own_pcap_bluetooth_h4_header);
495         hdr.pkt_encap = WTAP_ENCAP_BLUETOOTH_H4_WITH_PHDR;
496     }
497     else if (extcap_dumper.encap == EXTCAP_ENCAP_ETHERNET) {
498         hdr.pkt_encap = WTAP_ENCAP_ETHERNET;
499     }
500     else {
501         hdr.pkt_encap = WTAP_ENCAP_WIRESHARK_UPPER_PDU;
502     }
503
504     if (!wtap_dump(extcap_dumper.dumper.wtap, &hdr, (const guint8 *) buffer, &err, &err_info)) {
505         cfile_write_failure_message("androiddump", NULL, fifo, err, err_info,
506                                     0, WTAP_FILE_TYPE_SUBTYPE_PCAP_NSEC);
507         return FALSE;
508     }
509
510     wtap_dump_flush(extcap_dumper.dumper.wtap);
511 #endif
512
513     return TRUE;
514 }
515
516
517 static socket_handle_t adb_connect(const char *server_ip, unsigned short *server_tcp_port) {
518     socket_handle_t    sock;
519     socklen_t          length;
520     struct sockaddr_in server;
521     struct sockaddr_in client;
522     int                status;
523     int                tries = 0;
524
525     memset(&server, 0x0, sizeof(server));
526
527     server.sin_family = AF_INET;
528     server.sin_port = GINT16_TO_BE(*server_tcp_port);
529     ws_inet_pton4(server_ip, &(server.sin_addr.s_addr));
530
531     if ((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET) {
532         g_warning("Cannot open system TCP socket: %s", strerror(errno));
533         return INVALID_SOCKET;
534     }
535
536     useNonBlockingConnectTimeout(sock);
537     while (tries < SOCKET_CONNECT_TIMEOUT_TRIES) {
538         status = connect(sock, (struct sockaddr *) &server, (socklen_t)sizeof(server));
539         tries += 1;
540         if (status != SOCKET_ERROR)
541             break;
542         g_usleep(SOCKET_CONNECT_DELAY_US);
543     }
544     useNormalConnectTimeout(sock);
545
546     if (status == SOCKET_ERROR) {
547 #if 0
548 /* NOTE: This does not work well - make significant delay while initializing Wireshark.
549          Do fork() then call "adb" also does not make sense, because there is need to
550          do something like sleep(1) to ensure adb is started... system() cannot be used
551          on Windows, because open console window. This helper does not work as expected,
552          so disable it and user must ensure that adb is started (adb start-server,
553          but also all other command start-server automatically)
554 */
555 #ifdef _WIN32
556         if (_execlp("adb", "adb", "start-server", NULL)) {
557 #else
558         if (execlp("adb", "adb", "start-server", NULL)) {
559 #endif
560             errmsg("WARNING: Cannot execute system command to start adb: %s", strerror(errno));
561             closesocket(sock);
562             return INVALID_SOCKET;
563         };
564
565         if (connect(sock, (struct sockaddr *) &server, (socklen_t)sizeof(server)) == SOCKET_ERROR) {
566             g_warning("Cannot connect to ADB: <%s> Please check that adb daemon is running.", strerror(errno));
567             closesocket(sock);
568             return INVALID_SOCKET;
569         }
570 #else
571     g_debug("Cannot connect to ADB: <%s> Please check that adb daemon is running.", strerror(errno));
572     closesocket(sock);
573     return INVALID_SOCKET;
574 #endif
575     }
576
577     length = sizeof(client);
578     if (getsockname(sock, (struct sockaddr *) &client, &length)) {
579         g_warning("getsockname: %s", strerror(errno));
580         closesocket(sock);
581         return INVALID_SOCKET;
582     }
583
584     if (length != sizeof(client)) {
585         g_warning("incorrect length");
586         closesocket(sock);
587         return INVALID_SOCKET;
588     }
589
590     g_debug("Client port %u", GUINT16_FROM_BE(client.sin_port));
591
592     return sock;
593 }
594
595
596 static char *adb_send_and_receive(socket_handle_t sock, const char *adb_service,
597         char *buffer, size_t buffer_length, size_t *data_length) {
598     size_t   used_buffer_length;
599     size_t   bytes_to_read;
600     guint32  length;
601     gssize   result;
602     char     status[4];
603     char     tmp_buffer;
604     size_t   adb_service_length;
605
606     adb_service_length = strlen(adb_service);
607     if (adb_service_length > INT_MAX) {
608         g_warning("Service name too long when sending <%s> to ADB daemon", adb_service);
609         if (data_length)
610             *data_length = 0;
611         return NULL;
612     }
613
614     /* 8 bytes of hex length + terminating NUL */
615     if (buffer_length < 9) {
616         g_warning("Buffer for response too short while sending <%s> to ADB daemon", adb_service);
617         if (data_length)
618             *data_length = 0;
619         return NULL;
620     }
621
622     g_snprintf(buffer, (gulong)buffer_length, ADB_HEX4_FORMAT, adb_service_length);
623     result = send(sock, buffer, ADB_HEX4_LEN, 0);
624     if (result < ADB_HEX4_LEN) {
625         g_warning("Error while sending <%s> length to ADB daemon", adb_service);
626         return NULL;
627     }
628
629     result = send(sock, adb_service, (int) adb_service_length, 0);
630     if (result != (gssize) adb_service_length) {
631         g_warning("Error while sending <%s> to ADB daemon", adb_service);
632         if (data_length)
633             *data_length = 0;
634         return NULL;
635     }
636
637     used_buffer_length = 0;
638     while (used_buffer_length < 8) {
639         bytes_to_read = buffer_length - used_buffer_length;
640         if (bytes_to_read > INT_MAX)
641             bytes_to_read = INT_MAX;
642         result = recv(sock, buffer + used_buffer_length,  (int)bytes_to_read, 0);
643
644         if (result <= 0) {
645             g_warning("Broken socket connection while fetching reply status for <%s>", adb_service);
646             if (data_length)
647                 *data_length = 0;
648             return NULL;
649         }
650
651         used_buffer_length += result;
652     }
653
654     memcpy(status, buffer, 4);
655     tmp_buffer = buffer[8];
656     buffer[8] = '\0';
657     if (!ws_hexstrtou32(buffer + 4, NULL, &length)) {
658         g_warning("Invalid reply length <%s> while reading reply for <%s>", buffer + 4, adb_service);
659         if (data_length)
660             *data_length = 0;
661         return NULL;
662     }
663     buffer[8] = tmp_buffer;
664
665     if (buffer_length < length + 8) {
666         g_warning("Buffer for response too short while sending <%s> to ADB daemon", adb_service);
667         if (data_length)
668             *data_length = 0;
669         return NULL;
670     }
671
672     while (used_buffer_length < length + 8) {
673         bytes_to_read = buffer_length - used_buffer_length;
674         if (bytes_to_read > INT_MAX)
675             bytes_to_read = INT_MAX;
676         result = recv(sock, buffer + used_buffer_length,  (int)bytes_to_read, 0);
677
678         if (result <= 0) {
679             g_warning("Broken socket connection while reading reply for <%s>", adb_service);
680             if (data_length)
681                 *data_length = 0;
682             return NULL;
683         }
684
685         used_buffer_length += result;
686     }
687
688     if (data_length)
689         *data_length = used_buffer_length - 8;
690
691     if (memcmp(status, "OKAY", 4)) {
692         g_warning("Error while receiving by ADB for <%s>", adb_service);
693         if (data_length)
694             *data_length = 0;
695         return NULL;
696     }
697
698     return buffer + 8;
699 }
700
701
702 static char *adb_send_and_read(socket_handle_t sock, const char *adb_service, char *buffer,
703         int buffer_length, gssize *data_length) {
704     gssize   used_buffer_length;
705     gssize   result;
706     char     status[4];
707     size_t   adb_service_length;
708
709     adb_service_length = strlen(adb_service);
710     g_snprintf(buffer, buffer_length, ADB_HEX4_FORMAT, adb_service_length);
711
712     result = send(sock, buffer, ADB_HEX4_LEN, 0);
713     if (result < ADB_HEX4_LEN) {
714         g_warning("Error while sending <%s> to ADB daemon", adb_service);
715         return NULL;
716     }
717
718     result = send(sock, adb_service, (int) adb_service_length, 0);
719     if (result != (gssize) adb_service_length) {
720         g_warning("Error while sending <%s> to ADB", adb_service);
721         if (data_length)
722             *data_length = 0;
723         return NULL;
724     }
725
726     used_buffer_length = 0;
727     while (used_buffer_length < 4) {
728         result = recv(sock, buffer + used_buffer_length,  (int)(buffer_length - used_buffer_length), 0);
729
730         if (result <= 0) {
731             g_warning("Broken socket connection while fetching reply status for <%s>", adb_service);
732
733             return NULL;
734         }
735
736         used_buffer_length += result;
737     }
738
739     memcpy(status, buffer, 4);
740
741     while (result > 0) {
742         result= recv(sock, buffer + used_buffer_length,  (int)(buffer_length - used_buffer_length), 0);
743
744         if (result < 0) {
745             g_warning("Broken socket connection while reading reply for <%s>", adb_service);
746
747             return NULL;
748         } else if (result == 0) {
749             break;
750         }
751
752         used_buffer_length += result;
753     }
754
755     if (data_length)
756         *data_length = used_buffer_length - 4;
757
758     if (memcmp(status, "OKAY", 4)) {
759         g_warning("Error while receiving by ADB for <%s>", adb_service);
760         if (data_length)
761             *data_length = 0;
762         return NULL;
763     }
764
765     return buffer + 4;
766 }
767
768
769 static int adb_send(socket_handle_t sock, const char *adb_service) {
770     char buffer[5];
771     int      used_buffer_length;
772     gssize   result;
773     size_t   adb_service_length;
774
775     adb_service_length = strlen(adb_service);
776     g_snprintf(buffer, sizeof(buffer), ADB_HEX4_FORMAT, adb_service_length);
777
778     result = send(sock, buffer, ADB_HEX4_LEN, 0);
779     if (result < ADB_HEX4_LEN) {
780         g_warning("Error while sending <%s> to ADB daemon", adb_service);
781         return EXIT_CODE_ERROR_WHILE_SENDING_ADB_PACKET_1;
782     }
783
784     result = send(sock, adb_service, (int) adb_service_length, 0);
785     if (result != (gssize) adb_service_length) {
786         g_warning("Error while sending <%s> to ADB", adb_service);
787         return EXIT_CODE_ERROR_WHILE_SENDING_ADB_PACKET_1;
788     }
789
790     used_buffer_length = 0;
791     while (used_buffer_length < 4) {
792         result = recv(sock, buffer + used_buffer_length, 4 - used_buffer_length, 0);
793
794         if (result <= 0) {
795             g_warning("Broken socket connection while fetching reply status for <%s>", adb_service);
796
797             return EXIT_CODE_ERROR_WHILE_RECEIVING_ADB_PACKET_STATUS;
798         }
799
800         used_buffer_length += (int)result;
801     }
802
803     if (memcmp(buffer, "OKAY", 4)) {
804         g_debug("Error while receiving by ADB for <%s>", adb_service);
805
806         return EXIT_CODE_ERROR_WHILE_RECEIVING_ADB_PACKET_DATA;
807     }
808
809     return EXIT_CODE_SUCCESS;
810 }
811
812
813 static socket_handle_t
814 adb_connect_transport(const char *server_ip, unsigned short *server_tcp_port,
815                       const char* serial_number)
816 {
817     static const char *const adb_transport_serial_templace = "host:transport:%s";
818     static const char *const adb_transport_any  = "host:transport-any";
819     char transport_buf[80];
820     const char* transport = transport_buf;
821     socket_handle_t sock;
822     gssize result;
823
824     sock = adb_connect(server_ip, server_tcp_port);
825     if (sock == INVALID_SOCKET) {
826         g_warning("Error while connecting to adb server");
827         return sock;
828     }
829
830     if (!serial_number) {
831         transport = adb_transport_any;
832     } else {
833         result = g_snprintf(transport_buf, sizeof(transport_buf), adb_transport_serial_templace, serial_number);
834         if (result <= 0 || result > (int)sizeof(transport_buf)) {
835             g_warning("Error while completing adb packet for transport");
836             closesocket(sock);
837             return INVALID_SOCKET;
838         }
839     }
840
841     result = adb_send(sock, transport);
842     if (result) {
843         g_warning("Error while setting adb transport for <%s>", transport_buf);
844         closesocket(sock);
845         return INVALID_SOCKET;
846     }
847     return sock;
848 }
849
850
851 static void new_interface(extcap_parameters * extcap_conf, const gchar *interface_id,
852         const gchar *model_name, const gchar *serial_number, const gchar *display_name)
853 {
854     char *interface = g_strdup_printf("%s-%s", interface_id, serial_number);
855     char *ifdisplay = g_strdup_printf("%s %s %s", display_name, model_name, serial_number);
856
857     if (is_specified_interface(interface, INTERFACE_ANDROID_BLUETOOTH_HCIDUMP) ||
858             is_specified_interface(interface, INTERFACE_ANDROID_BLUETOOTH_EXTERNAL_PARSER) ||
859             is_specified_interface(interface, INTERFACE_ANDROID_BLUETOOTH_BTSNOOP_NET)) {
860
861         extcap_base_register_interface_ext(extcap_conf, interface, ifdisplay, 99, "BluetoothH4", "Bluetooth HCI UART transport layer plus pseudo-header" );
862     } else if (is_logcat_interface(interface) || is_logcat_text_interface(interface)) {
863         extcap_base_register_interface(extcap_conf, interface, ifdisplay, 252, "Upper PDU" );
864     } else if (is_specified_interface(interface, INTERFACE_ANDROID_TCPDUMP)) {
865         extcap_base_register_interface(extcap_conf, interface, ifdisplay, 1, "Ethernet");
866     }
867     g_free(interface);
868     g_free(ifdisplay);
869 }
870
871
872 static void new_fake_interface_for_list_dlts(extcap_parameters * extcap_conf,
873         const gchar *ifname)
874 {
875     if (is_specified_interface(ifname, INTERFACE_ANDROID_BLUETOOTH_HCIDUMP) ||
876             is_specified_interface(ifname, INTERFACE_ANDROID_BLUETOOTH_EXTERNAL_PARSER) ||
877             is_specified_interface(ifname, INTERFACE_ANDROID_BLUETOOTH_BTSNOOP_NET)) {
878         extcap_base_register_interface_ext(extcap_conf, ifname, ifname, 99, "BluetoothH4", "Bluetooth HCI UART transport layer plus pseudo-header" );
879     } else if (is_logcat_interface(ifname) || is_logcat_text_interface(ifname)) {
880         extcap_base_register_interface(extcap_conf, ifname, ifname, 252, "Upper PDU" );
881     } else if (is_specified_interface(ifname, INTERFACE_ANDROID_TCPDUMP)) {
882         extcap_base_register_interface(extcap_conf, ifname, ifname, 1, "Ethernet");
883     }
884 }
885
886
887 static int add_tcpdump_interfaces(extcap_parameters * extcap_conf, const char *adb_server_ip, unsigned short *adb_server_tcp_port, const char *serial_number)
888 {
889     static const char *const adb_tcpdump_list = "shell:tcpdump -D";
890     static const char *const regex_ifaces = "\\d+\\.(?<iface>\\S+)(\\s+?(?:(?:\\(.*\\))*)(\\s*?\\[(?<flags>.*?)\\])?)?";
891     static char recv_buffer[PACKET_LENGTH];
892     char *response;
893     gssize data_length;
894     socket_handle_t sock;
895     GRegex* regex = NULL;
896     GError *err = NULL;
897     GMatchInfo *match = NULL;
898     char* tok;
899     char iface_name[80];
900     gboolean flags_supported;
901
902     sock = adb_connect_transport(adb_server_ip, adb_server_tcp_port, serial_number);
903     if (sock == INVALID_SOCKET) {
904         g_warning("Failed to connect to adb server");
905         return EXIT_CODE_GENERIC;
906     }
907
908     response = adb_send_and_read(sock, adb_tcpdump_list, recv_buffer, sizeof(recv_buffer), &data_length);
909     closesocket(sock);
910
911     if (!response) {
912         g_warning("Failed to get list of available tcpdump interfaces");
913         return EXIT_CODE_GENERIC;
914     }
915     response[data_length] = '\0';
916
917     regex = g_regex_new(regex_ifaces, (GRegexCompileFlags)0, (GRegexMatchFlags)0, &err);
918     if (!regex) {
919         g_warning("Failed to compile regex for tcpdump interface matching");
920         return EXIT_CODE_GENERIC;
921     }
922
923     flags_supported = (strstr(response, "[") != 0) && (strstr(response, "]") != 0);
924
925     tok = strtok(response, "\n");
926     while (tok != NULL) {
927         g_regex_match(regex, tok, (GRegexMatchFlags)0, &match);
928         if (g_match_info_matches(match)) {
929             gchar *iface = g_match_info_fetch_named(match, "iface");
930             gchar *flags = g_match_info_fetch_named(match, "flags");
931
932             if (!flags_supported || (flags && strstr(flags, "Up"))) {
933                 g_snprintf(iface_name, sizeof(iface_name), INTERFACE_ANDROID_TCPDUMP_FORMAT, iface);
934                 new_interface(extcap_conf, iface_name, iface, serial_number, "Android tcpdump");
935             }
936             g_free(flags);
937             g_free(iface);
938         }
939         g_match_info_free(match);
940         tok = strtok(NULL, "\n");
941     }
942     g_regex_unref(regex);
943     return 0;
944 }
945
946
947 static int register_interfaces(extcap_parameters * extcap_conf, const char *adb_server_ip, unsigned short *adb_server_tcp_port) {
948     static char            packet[PACKET_LENGTH];
949     static char            helpful_packet[PACKET_LENGTH];
950     char                   check_port_buf[80];
951     char                  *response;
952     char                  *device_list;
953     gssize                 data_length;
954     size_t                 device_length;
955     socket_handle_t        sock;
956     const char            *adb_check_port_templace       = "shell:cat /proc/%s/net/tcp";
957     const char            *adb_devices            = "host:devices-l";
958     const char            *adb_api_level          = "shell:getprop ro.build.version.sdk";
959     const char            *adb_hcidump_version    = "shell:hcidump --version";
960     const char            *adb_ps_droid_bluetooth = "shell:ps droid.bluetooth";
961     const char            *adb_ps_bluetooth_app   = "shell:ps com.android.bluetooth";
962     const char            *adb_ps_with_grep       = "shell:ps | grep com.android.bluetooth";
963     char                   serial_number[SERIAL_NUMBER_LENGTH_MAX];
964     char                   model_name[MODEL_NAME_LENGTH_MAX];
965     int                    result;
966     char                  *pos;
967     char                  *i_pos;
968     char                  *model_pos;
969     char                  *device_pos;
970     char                  *prev_pos;
971     int                    api_level;
972     int                    disable_interface;
973
974 /* NOTE: It seems that "adb devices" and "adb shell" closed connection
975          so cannot send next command after them, there is need to reconnect */
976
977     sock = adb_connect(adb_server_ip, adb_server_tcp_port);
978     if (sock == INVALID_SOCKET)
979         return EXIT_CODE_INVALID_SOCKET_INTERFACES_LIST;
980
981     device_list = adb_send_and_receive(sock, adb_devices, packet, sizeof(packet), &device_length);
982     closesocket(sock);
983
984     if (!device_list) {
985         g_warning("Cannot get list of interfaces from devices");
986
987         return EXIT_CODE_CANNOT_GET_INTERFACES_LIST;
988     }
989
990     device_list[device_length] = '\0';
991     pos = (char *) device_list;
992
993     while (pos < (char *) (device_list + device_length)) {
994         prev_pos = pos;
995         pos = strchr(pos, ' ');
996         i_pos = pos;
997         result = (int) (pos - prev_pos);
998         pos = strchr(pos, '\n') + 1;
999         if (result >= (int) sizeof(serial_number)) {
1000             g_warning("Serial number too long, ignore device");
1001             continue;
1002         }
1003         memcpy(serial_number, prev_pos, result);
1004         serial_number[result] = '\0';
1005
1006         model_name[0] = '\0';
1007         model_pos = g_strstr_len(i_pos, pos - i_pos, "model:");
1008         if (model_pos) {
1009             device_pos = g_strstr_len(i_pos, pos - i_pos, "device:");
1010             if (device_pos && device_pos - model_pos - 6 - 1 < MODEL_NAME_LENGTH_MAX) {
1011                 memcpy(model_name, model_pos + 6, device_pos - model_pos - 6 - 1);
1012                 model_name[device_pos - model_pos - 6 - 1] = '\0';
1013             }
1014         }
1015
1016         if (model_name[0] == '\0')
1017             strcpy(model_name, "unknown");
1018
1019         g_debug("Processing device: \"%s\" <%s>" , serial_number, model_name);
1020
1021         /* Function will only add tcpdump interfaces if tcpdump is present on the device */
1022         result = add_tcpdump_interfaces(extcap_conf, adb_server_ip, adb_server_tcp_port, serial_number  );
1023         if (result) {
1024             g_warning("Error while adding tcpdump interfaces");
1025         }
1026
1027         sock = adb_connect_transport(adb_server_ip, adb_server_tcp_port, serial_number);
1028         if (sock == INVALID_SOCKET) continue;
1029
1030         response = adb_send_and_read(sock, adb_api_level, helpful_packet, sizeof(helpful_packet), &data_length);
1031         closesocket(sock);
1032
1033         if (!response) {
1034             g_warning("Error on socket: <%s>", helpful_packet);
1035             continue;
1036         }
1037
1038         response[data_length] = '\0';
1039         api_level = (int) g_ascii_strtoll(response, NULL, 10);
1040         g_debug("Android API Level for %s is %i", serial_number, api_level);
1041
1042         if (api_level < 21) {
1043             new_interface(extcap_conf, INTERFACE_ANDROID_LOGCAT_MAIN,   model_name, serial_number, "Android Logcat Main");
1044             new_interface(extcap_conf, INTERFACE_ANDROID_LOGCAT_SYSTEM, model_name, serial_number, "Android Logcat System");
1045             new_interface(extcap_conf, INTERFACE_ANDROID_LOGCAT_RADIO,  model_name, serial_number, "Android Logcat Radio");
1046             new_interface(extcap_conf, INTERFACE_ANDROID_LOGCAT_EVENTS, model_name, serial_number, "Android Logcat Events");
1047
1048             new_interface(extcap_conf, INTERFACE_ANDROID_LOGCAT_TEXT_MAIN,   model_name, serial_number, "Android Logcat Main");
1049             new_interface(extcap_conf, INTERFACE_ANDROID_LOGCAT_TEXT_SYSTEM, model_name, serial_number, "Android Logcat System");
1050             new_interface(extcap_conf, INTERFACE_ANDROID_LOGCAT_TEXT_RADIO,  model_name, serial_number, "Android Logcat Radio");
1051             new_interface(extcap_conf, INTERFACE_ANDROID_LOGCAT_TEXT_EVENTS, model_name, serial_number, "Android Logcat Events");
1052         } else {
1053             new_interface(extcap_conf, INTERFACE_ANDROID_LOGCAT_TEXT_MAIN,   model_name, serial_number, "Android Logcat Main");
1054             new_interface(extcap_conf, INTERFACE_ANDROID_LOGCAT_TEXT_SYSTEM, model_name, serial_number, "Android Logcat System");
1055             new_interface(extcap_conf, INTERFACE_ANDROID_LOGCAT_TEXT_RADIO,  model_name, serial_number, "Android Logcat Radio");
1056             new_interface(extcap_conf, INTERFACE_ANDROID_LOGCAT_TEXT_EVENTS, model_name, serial_number, "Android Logcat Events");
1057             new_interface(extcap_conf, INTERFACE_ANDROID_LOGCAT_TEXT_CRASH,  model_name, serial_number, "Android Logcat Crash");
1058         }
1059
1060         if (api_level >= 5 && api_level < 17) {
1061             disable_interface = 0;
1062
1063             sock = adb_connect_transport(adb_server_ip, adb_server_tcp_port, serial_number);
1064             if (sock == INVALID_SOCKET) continue;
1065
1066             response = adb_send_and_read(sock, adb_hcidump_version, helpful_packet, sizeof(helpful_packet), &data_length);
1067             closesocket(sock);
1068
1069             if (!response || data_length < 1) {
1070                 g_warning("Error while getting hcidump version by <%s> (%p len=%"G_GSSIZE_FORMAT")",
1071                     adb_hcidump_version, (void*)response, data_length);
1072                 g_debug("Android hcidump version for %s is unknown", serial_number);
1073                 disable_interface = 1;
1074             } else {
1075                 response[data_length] = '\0';
1076
1077                 if (g_ascii_strtoull(response, NULL, 10) == 0) {
1078                     g_debug("Android hcidump version for %s is unknown", serial_number);
1079                     disable_interface = 1;
1080                 } else {
1081                     g_debug("Android hcidump version for %s is %s", serial_number, response);
1082                 }
1083             }
1084
1085             if (!disable_interface) {
1086                 new_interface(extcap_conf, INTERFACE_ANDROID_BLUETOOTH_HCIDUMP, model_name, serial_number, "Android Bluetooth Hcidump");
1087             }
1088         }
1089
1090         if (api_level >= 17 && api_level < 21) {
1091             disable_interface = 0;
1092             sock = adb_connect_transport(adb_server_ip, adb_server_tcp_port, serial_number);
1093             if (sock == INVALID_SOCKET) continue;
1094
1095             response = adb_send_and_read(sock, adb_ps_droid_bluetooth, helpful_packet, sizeof(helpful_packet), &data_length);
1096             closesocket(sock);
1097             if (!response || data_length < 1) {
1098                 g_warning("Error while getting Bluetooth application process id by <%s> "
1099                     "(%p len=%"G_GSSIZE_FORMAT")", adb_hcidump_version, (void*)response, data_length);
1100                 g_debug( "Android Bluetooth application PID for %s is unknown", serial_number);
1101                 disable_interface = 1;
1102             } else {
1103                 char  *data_str;
1104                 char   pid[16];
1105
1106                 memset(pid, 0, sizeof(pid));
1107                 response[data_length] = '\0';
1108
1109                 data_str = strchr(response, '\n');
1110                 if (data_str && sscanf(data_str, "%*s %15s", pid) == 1) {
1111                     g_debug("Android Bluetooth application PID for %s is %s", serial_number, pid);
1112
1113                     result = g_snprintf(check_port_buf, sizeof(check_port_buf), adb_check_port_templace, pid);
1114                     if (result <= 0 || result > (int)sizeof(check_port_buf)) {
1115                         g_warning("Error while completing adb packet");
1116                         return EXIT_CODE_BAD_SIZE_OF_ASSEMBLED_ADB_PACKET_6;
1117                     }
1118
1119                     sock = adb_connect_transport(adb_server_ip, adb_server_tcp_port, serial_number);
1120                     if (sock == INVALID_SOCKET) continue;
1121
1122                     response = adb_send_and_read(sock, check_port_buf, helpful_packet, sizeof(helpful_packet), &data_length);
1123                     closesocket(sock);
1124
1125                     if (!response) {
1126                         disable_interface = 1;
1127                     } else {
1128                         response[data_length] = '\0';
1129
1130                         data_str = strchr(response, '\n');
1131                         if (data_str && sscanf(data_str, "%*s %15s", pid) == 1 && strlen(pid) > 10 && strcmp(pid + 9, "10EA") == 0) {
1132                             g_debug("Bluedroid External Parser Port for %s is %s", serial_number, pid + 9);
1133                         } else {
1134                             disable_interface = 1;
1135                             g_debug("Bluedroid External Parser Port for %s is unknown", serial_number);
1136                         }
1137                     }
1138                 } else {
1139                     disable_interface = 1;
1140                     g_debug("Android Bluetooth application PID for %s is unknown", serial_number);
1141                 }
1142             }
1143
1144             if (!disable_interface) {
1145                 new_interface(extcap_conf, INTERFACE_ANDROID_BLUETOOTH_EXTERNAL_PARSER, model_name, serial_number, "Android Bluetooth External Parser");
1146             }
1147         }
1148
1149         if (api_level >= 21) {
1150             const char* ps_cmd;
1151             disable_interface = 0;
1152
1153             if (api_level >= 24) {
1154                 ps_cmd = adb_ps_with_grep;
1155             } else if (api_level >= 23) {
1156                 ps_cmd = adb_ps_bluetooth_app;
1157             }  else {
1158                 ps_cmd = adb_ps_droid_bluetooth;
1159             }
1160             sock = adb_connect_transport(adb_server_ip, adb_server_tcp_port, serial_number);
1161             if (sock == INVALID_SOCKET) continue;
1162
1163             response = adb_send_and_read(sock, ps_cmd, helpful_packet, sizeof(helpful_packet), &data_length);
1164             closesocket(sock);
1165
1166             if (!response || data_length < 1) {
1167                 g_warning("Error while getting Bluetooth application process id by <%s> "
1168                     "(%p len=%"G_GSSIZE_FORMAT")", adb_hcidump_version, (void*)response, data_length);
1169                 g_debug("Android Bluetooth application PID for %s is unknown", serial_number);
1170                 disable_interface = 1;
1171             } else {
1172                 char  *data_str;
1173                 char   pid[16];
1174
1175                 memset(pid, 0, sizeof(pid));
1176                 response[data_length] = '\0';
1177
1178                 if (api_level >= 24)
1179                     data_str = response;
1180                 else
1181                     data_str = strchr(response, '\n');
1182
1183                 if (data_str && sscanf(data_str, "%*s %15s", pid) == 1) {
1184                     g_debug("Android Bluetooth application PID for %s is %s", serial_number, pid);
1185
1186                     result = g_snprintf(check_port_buf, sizeof(check_port_buf), adb_check_port_templace, pid);
1187                     if (result <= 0 || result > (int)sizeof(check_port_buf)) {
1188                         g_warning("Error while completing adb packet");
1189                         return EXIT_CODE_BAD_SIZE_OF_ASSEMBLED_ADB_PACKET_9;
1190                     }
1191
1192                     sock = adb_connect_transport(adb_server_ip, adb_server_tcp_port, serial_number);
1193                     if (sock == INVALID_SOCKET) continue;
1194
1195                     response = adb_send_and_read(sock, check_port_buf, helpful_packet, sizeof(helpful_packet), &data_length);
1196                     closesocket(sock);
1197
1198                     if (!response) {
1199                         disable_interface = 1;
1200                     } else {
1201                         response[data_length] = '\0';
1202
1203                         data_str = strchr(response, '\n');
1204                         if (data_str && sscanf(data_str, "%*s %15s", pid) == 1 && strlen(pid) > 10 && strcmp(pid + 9, "22A8") == 0) {
1205                             g_debug("Btsnoop Net Port for %s is %s", serial_number, pid + 9);
1206                         } else {
1207                             disable_interface = 1;
1208                             g_debug("Btsnoop Net Port for %s is unknown", serial_number);
1209                         }
1210                     }
1211                 } else {
1212                     disable_interface = 1;
1213                     g_debug("Android Bluetooth application PID for %s is unknown", serial_number);
1214                 }
1215             }
1216
1217             if (!disable_interface) {
1218                 new_interface(extcap_conf, INTERFACE_ANDROID_BLUETOOTH_BTSNOOP_NET, model_name, serial_number, "Android Bluetooth Btsnoop Net");
1219             }
1220         }
1221     }
1222
1223     return EXIT_CODE_SUCCESS;
1224 }
1225
1226 static int list_config(char *interface) {
1227     int ret = EXIT_CODE_INVALID_INTERFACE;
1228     unsigned inc = 0;
1229
1230     if (!interface) {
1231         g_warning("No interface specified.");
1232         return EXIT_CODE_NO_INTERFACE_SPECIFIED;
1233     }
1234
1235     if (is_specified_interface(interface, INTERFACE_ANDROID_BLUETOOTH_EXTERNAL_PARSER)) {
1236         printf("arg {number=%u}{call=--adb-server-ip}{display=ADB Server IP Address}{type=string}{default=127.0.0.1}\n", inc++);
1237         printf("arg {number=%u}{call=--adb-server-tcp-port}{display=ADB Server TCP Port}{type=integer}{range=0,65535}{default=5037}\n", inc++);
1238         printf("arg {number=%u}{call=--bt-server-tcp-port}{display=Bluetooth Server TCP Port}{type=integer}{range=0,65535}{default=4330}\n", inc++);
1239         printf("arg {number=%u}{call=--bt-forward-socket}{display=Forward Bluetooth Socket}{type=boolean}{default=false}\n", inc++);
1240         printf("arg {number=%u}{call=--bt-local-ip}{display=Bluetooth Local IP Address}{type=string}{default=127.0.0.1}\n", inc++);
1241         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++);
1242         printf("arg {number=%u}{call=--verbose}{display=Verbose/Debug output on console}{type=boolean}{default=false}\n", inc++);
1243         ret = EXIT_CODE_SUCCESS;
1244     } else  if (is_specified_interface(interface, INTERFACE_ANDROID_BLUETOOTH_HCIDUMP) ||
1245             is_specified_interface(interface, INTERFACE_ANDROID_BLUETOOTH_BTSNOOP_NET) ||
1246             is_specified_interface(interface, INTERFACE_ANDROID_TCPDUMP)) {
1247         printf("arg {number=%u}{call=--adb-server-ip}{display=ADB Server IP Address}{type=string}{default=127.0.0.1}\n", inc++);
1248         printf("arg {number=%u}{call=--adb-server-tcp-port}{display=ADB Server TCP Port}{type=integer}{range=0,65535}{default=5037}\n", inc++);
1249         printf("arg {number=%u}{call=--verbose}{display=Verbose/Debug output on console}{type=boolean}{default=false}\n", inc++);
1250         ret = EXIT_CODE_SUCCESS;
1251     } else if (is_logcat_interface(interface)) {
1252         printf("arg {number=%u}{call=--adb-server-ip}{display=ADB Server IP Address}{type=string}{default=127.0.0.1}\n", inc++);
1253         printf("arg {number=%u}{call=--adb-server-tcp-port}{display=ADB Server TCP Port}{type=integer}{range=0,65535}{default=5037}\n", inc++);
1254         printf("arg {number=%u}{call=--logcat-text}{display=Use text logcat}{type=boolean}{default=false}\n", inc++);
1255         printf("arg {number=%u}{call=--logcat-ignore-log-buffer}{display=Ignore log buffer}{type=boolean}{default=false}\n", inc++);
1256         printf("arg {number=%u}{call=--logcat-custom-options}{display=Custom logcat parameters}{type=string}\n", inc++);
1257         printf("arg {number=%u}{call=--verbose}{display=Verbose/Debug output on console}{type=boolean}{default=false}\n", inc++);
1258         ret = EXIT_CODE_SUCCESS;
1259     } else if (is_logcat_text_interface(interface)) {
1260         printf("arg {number=%u}{call=--adb-server-ip}{display=ADB Server IP Address}{type=string}{default=127.0.0.1}\n", inc++);
1261         printf("arg {number=%u}{call=--adb-server-tcp-port}{display=ADB Server TCP Port}{type=integer}{range=0,65535}{default=5037}\n", inc++);
1262         printf("arg {number=%u}{call=--logcat-ignore-log-buffer}{display=Ignore log buffer}{type=boolean}{default=false}\n", inc++);
1263         printf("arg {number=%u}{call=--logcat-custom-options}{display=Custom logcat parameters}{type=string}\n", inc++);
1264         printf("arg {number=%u}{call=--verbose}{display=Verbose/Debug output on console}{type=boolean}{default=false}\n", inc++);
1265         ret = EXIT_CODE_SUCCESS;
1266     }
1267
1268     if (ret != EXIT_CODE_SUCCESS)
1269         g_warning("Invalid interface: <%s>", interface);
1270     else
1271         extcap_config_debug(&inc);
1272
1273     return ret;
1274 }
1275
1276 /*----------------------------------------------------------------------------*/
1277 /* Android Bluetooth Hcidump */
1278 /*----------------------------------------------------------------------------*/
1279
1280 static int capture_android_bluetooth_hcidump(char *interface, char *fifo,
1281         const char *adb_server_ip, unsigned short *adb_server_tcp_port) {
1282     struct extcap_dumper           extcap_dumper;
1283     static char                    data[PACKET_LENGTH];
1284     static char                    packet[PACKET_LENGTH];
1285     gssize                         length;
1286     gssize                         used_buffer_length = 0;
1287     socket_handle_t                sock = INVALID_SOCKET;
1288     const char                    *adb_shell_hcidump = "shell:hcidump -R -t";
1289     const char                    *adb_shell_su_hcidump = "shell:su -c hcidump -R -t";
1290     int                            result;
1291     char                          *serial_number;
1292     time_t                         ts = 0;
1293     unsigned int                   captured_length;
1294     gint64                         hex;
1295     char                          *hex_data;
1296     char                          *new_hex_data;
1297     own_pcap_bluetooth_h4_header  *h4_header;
1298     gint64                         raw_length = 0;
1299     gint64                         frame_length;
1300     int                            ms = 0;
1301     struct tm                      date;
1302     char                           direction_character;
1303
1304     SET_DATA(h4_header, value_own_pcap_bluetooth_h4_header, packet);
1305
1306     extcap_dumper = extcap_dumper_open(fifo, EXTCAP_ENCAP_BLUETOOTH_H4_WITH_PHDR);
1307
1308     serial_number = get_serial_from_interface(interface);
1309     sock = adb_connect_transport(adb_server_ip, adb_server_tcp_port, serial_number);
1310     if (sock == INVALID_SOCKET)
1311         return EXIT_CODE_INVALID_SOCKET_3;
1312
1313     result = adb_send(sock, adb_shell_hcidump);
1314     if (result) {
1315         g_warning("Error while starting capture by sending command: %s", adb_shell_hcidump);
1316         closesocket(sock);
1317         return EXIT_CODE_GENERIC;
1318     }
1319
1320     while (endless_loop) {
1321         char  *i_position;
1322
1323         errno = 0;
1324         length = recv(sock, data + used_buffer_length, (int)(PACKET_LENGTH - used_buffer_length), 0);
1325         if (errno == EAGAIN
1326 #if EWOULDBLOCK != EAGAIN
1327             || errno == EWOULDBLOCK
1328 #endif
1329             ) {
1330             continue;
1331         }
1332         else if (errno != 0) {
1333             g_warning("ERROR capture: %s", strerror(errno));
1334             closesocket(sock);
1335             return EXIT_CODE_GENERIC;
1336         }
1337
1338         if (length <= 0) {
1339             g_warning("Broken socket connection.");
1340             closesocket(sock);
1341             return EXIT_CODE_GENERIC;
1342         }
1343
1344         used_buffer_length += length;
1345         i_position =  (char *) memchr(data, '\n', used_buffer_length);
1346         if (i_position && i_position < data + used_buffer_length) {
1347             char *state_line_position = i_position + 1;
1348
1349             if (!strncmp(data, "/system/bin/sh: hcidump: not found", 34)) {
1350                 g_warning("Command not found for <%s>", adb_shell_hcidump);
1351                 closesocket(sock);
1352                 return EXIT_CODE_GENERIC;
1353             }
1354
1355             i_position =  (char *) memchr(i_position + 1, '\n', used_buffer_length);
1356             if (i_position) {
1357                 i_position += 1;
1358                 if (!strncmp(state_line_position, "Can't access device: Permission denied", 38)) {
1359                     g_warning("No permission for command <%s>", adb_shell_hcidump);
1360                     used_buffer_length = 0;
1361                     closesocket(sock);
1362                     sock = INVALID_SOCKET;
1363                     break;
1364                 }
1365                 memmove(data, i_position, used_buffer_length - (i_position - data));
1366                 used_buffer_length = used_buffer_length - (gssize)(i_position - data);
1367                 break;
1368             }
1369         }
1370     }
1371
1372     if (sock == INVALID_SOCKET) {
1373         sock = adb_connect_transport(adb_server_ip, adb_server_tcp_port, serial_number);
1374         if (sock == INVALID_SOCKET)
1375             return EXIT_CODE_INVALID_SOCKET_4;
1376
1377         result = adb_send(sock, adb_shell_su_hcidump);
1378         if (result) {
1379             g_warning("Error while starting capture by sending command: <%s>", adb_shell_su_hcidump);
1380             closesocket(sock);
1381             return EXIT_CODE_GENERIC;
1382         }
1383
1384         used_buffer_length = 0;
1385         while (endless_loop) {
1386             char  *i_position;
1387
1388             errno = 0;
1389             length = recv(sock, data + used_buffer_length, (int)(PACKET_LENGTH - used_buffer_length), 0);
1390             if (errno == EAGAIN
1391 #if EWOULDBLOCK != EAGAIN
1392                 || errno == EWOULDBLOCK
1393 #endif
1394                 ) {
1395                 continue;
1396             }
1397             else if (errno != 0) {
1398                 g_warning("ERROR capture: %s", strerror(errno));
1399                 closesocket(sock);
1400                 return EXIT_CODE_GENERIC;
1401             }
1402
1403             if (length <= 0) {
1404                 g_warning("Broken socket connection.");
1405                 closesocket(sock);
1406                 return EXIT_CODE_GENERIC;
1407             }
1408
1409             used_buffer_length += length;
1410             i_position =  (char *) memchr(data, '\n', used_buffer_length);
1411             if (i_position && i_position < data + used_buffer_length) {
1412                 if (!strncmp(data, "/system/bin/sh: su: not found", 29)) {
1413                     g_warning("Command 'su' not found for <%s>", adb_shell_su_hcidump);
1414                     closesocket(sock);
1415                     return EXIT_CODE_GENERIC;
1416                 }
1417
1418                 i_position =  (char *) memchr(i_position + 1, '\n', used_buffer_length);
1419                 if (i_position) {
1420                     i_position += 1;
1421                     memmove(data, i_position, used_buffer_length - (i_position - data));
1422                     used_buffer_length = used_buffer_length - (gssize)(i_position - data);
1423                     break;
1424                 }
1425             }
1426         }
1427     }
1428
1429     while (endless_loop) {
1430         errno = 0;
1431         length = recv(sock, data + used_buffer_length,  (int)(PACKET_LENGTH - used_buffer_length), 0);
1432         if (errno == EAGAIN
1433 #if EWOULDBLOCK != EAGAIN
1434             || errno == EWOULDBLOCK
1435 #endif
1436             ) {
1437             continue;
1438         }
1439         else if (errno != 0) {
1440             g_warning("ERROR capture: %s", strerror(errno));
1441             closesocket(sock);
1442             return EXIT_CODE_GENERIC;
1443         }
1444
1445         if (length <= 0) {
1446             g_warning("Broken socket connection.");
1447             closesocket(sock);
1448             return EXIT_CODE_GENERIC;
1449         }
1450
1451         while (endless_loop) {
1452             if (used_buffer_length + length >= 1) {
1453                 hex_data = data + 29;
1454                 hex = g_ascii_strtoll(hex_data, &new_hex_data, 16);
1455
1456                 if  ((hex == 0x01 && used_buffer_length + length >= 4) ||
1457                         (hex == 0x02 && used_buffer_length + length >= 5) ||
1458                         (hex == 0x04 && used_buffer_length + length >= 3)) {
1459
1460                     if (hex == 0x01) {
1461                         hex_data = new_hex_data;
1462                         hex = g_ascii_strtoll(hex_data, &new_hex_data, 16);
1463                         if (hex < 0 || hex >= 256 || hex_data == new_hex_data) {
1464                             g_warning("data format %s", strerror(errno));
1465                             closesocket(sock);
1466                             return EXIT_CODE_GENERIC;
1467                         }
1468
1469                         hex_data = new_hex_data;
1470                         hex = g_ascii_strtoll(hex_data, &new_hex_data, 16);
1471                         if (hex < 0 || hex >= 256 || hex_data == new_hex_data) {
1472                             g_warning("data format %s", strerror(errno));
1473                             closesocket(sock);
1474                             return EXIT_CODE_GENERIC;
1475                         }
1476
1477                         hex_data = new_hex_data;
1478                         hex = g_ascii_strtoll(hex_data, &new_hex_data, 16);
1479
1480                         raw_length = hex + 4;
1481                     } else if (hex == 0x04) {
1482                         hex_data = new_hex_data;
1483                         hex = g_ascii_strtoll(hex_data, &new_hex_data, 16);
1484                         if (hex < 0 || hex >= 256 || hex_data == new_hex_data) {
1485                             g_warning("data format %s", strerror(errno));
1486                             closesocket(sock);
1487                             return EXIT_CODE_GENERIC;
1488                         }
1489
1490                         hex_data = new_hex_data;
1491                         hex = g_ascii_strtoll(hex_data, &new_hex_data, 16);
1492
1493                         raw_length = hex + 3;
1494                     } else if (hex == 0x02) {
1495                         hex_data = new_hex_data;
1496                         hex = g_ascii_strtoll(hex_data, &new_hex_data, 16);
1497                         if (hex < 0 || hex >= 256 || hex_data == new_hex_data) {
1498                             g_warning("data format %s", strerror(errno));
1499                             closesocket(sock);
1500                             return EXIT_CODE_GENERIC;
1501                         }
1502
1503                         hex_data = new_hex_data;
1504                         hex = g_ascii_strtoll(hex_data, &new_hex_data, 16);
1505                         if (hex < 0 || hex >= 256 || hex_data == new_hex_data) {
1506                             g_warning("data format %s", strerror(errno));
1507                             closesocket(sock);
1508                             return EXIT_CODE_GENERIC;
1509                         }
1510
1511                         hex_data = new_hex_data;
1512                         hex = g_ascii_strtoll(hex_data, &new_hex_data, 16);
1513                         raw_length = hex + 5;
1514
1515                         hex_data = new_hex_data;
1516                         hex = g_ascii_strtoll(hex_data, &new_hex_data, 16);
1517                         raw_length += hex << 8;
1518                     }
1519
1520                 } else {
1521                     g_warning("bad raw stream");
1522                     closesocket(sock);
1523                     return EXIT_CODE_GENERIC;
1524                 }
1525             } else {
1526                 used_buffer_length += length;
1527                 break;
1528             }
1529
1530             frame_length = raw_length * 3 + (raw_length / 20) * 4 + ((raw_length % 20) ? 2 : -2) + 29;
1531
1532             if (used_buffer_length + length < frame_length) {
1533                 used_buffer_length += length;
1534                 break;
1535             }
1536
1537             if (8 == sscanf(data, "%04d-%02d-%02d %02d:%02d:%02d.%06d %c",
1538                     &date.tm_year, &date.tm_mon, &date.tm_mday, &date.tm_hour,
1539                     &date.tm_min, &date.tm_sec, &ms, &direction_character)) {
1540
1541                 g_debug("time %04d-%02d-%02d %02d:%02d:%02d.%06d %c",
1542                             date.tm_year, date.tm_mon, date.tm_mday, date.tm_hour,
1543                             date.tm_min, date.tm_sec, ms, direction_character);
1544                 date.tm_mon -= 1;
1545                 date.tm_year -= 1900;
1546                 ts = mktime(&date);
1547
1548                 new_hex_data = data + 29;
1549             }
1550
1551             captured_length = 0;
1552
1553             while ((long)(new_hex_data - data + sizeof(own_pcap_bluetooth_h4_header)) < frame_length) {
1554                 hex_data = new_hex_data;
1555                 hex = g_ascii_strtoll(hex_data, &new_hex_data, 16);
1556
1557                 packet[sizeof(own_pcap_bluetooth_h4_header) + captured_length] = (char) hex;
1558                 captured_length += 1;
1559             }
1560
1561             h4_header->direction = GINT32_TO_BE(direction_character == '>');
1562
1563             endless_loop = extcap_dumper_dump(extcap_dumper, fifo, packet,
1564                     captured_length + sizeof(own_pcap_bluetooth_h4_header),
1565                     captured_length + sizeof(own_pcap_bluetooth_h4_header),
1566                     ts,
1567                     ms * 1000);
1568
1569             if (used_buffer_length + length >= frame_length) {
1570                 memmove(data, data + frame_length, (size_t)(used_buffer_length + length - frame_length));
1571                 used_buffer_length = (gssize)(used_buffer_length + length - frame_length);
1572                 length = 0;
1573                 continue;
1574             }
1575             length = 0;
1576         }
1577     }
1578
1579     closesocket(sock);
1580     return EXIT_CODE_SUCCESS;
1581 }
1582
1583 /*----------------------------------------------------------------------------*/
1584 /* Android Bluetooth External Parser */
1585 /*----------------------------------------------------------------------------*/
1586
1587 #define BLUEDROID_H4_PACKET_TYPE  0
1588 #define BLUEDROID_TIMESTAMP_SIZE  8
1589 #define BLUEDROID_H4_SIZE  1
1590
1591 static const uint64_t BLUEDROID_TIMESTAMP_BASE = G_GUINT64_CONSTANT(0x00dcddb30f2f8000);
1592
1593 #define BLUEDROID_H4_PACKET_TYPE_HCI_CMD  0x01
1594 #define BLUEDROID_H4_PACKET_TYPE_ACL      0x02
1595 #define BLUEDROID_H4_PACKET_TYPE_SCO      0x03
1596 #define BLUEDROID_H4_PACKET_TYPE_HCI_EVT  0x04
1597
1598 #define BLUEDROID_DIRECTION_SENT  0
1599 #define BLUEDROID_DIRECTION_RECV  1
1600
1601 static int adb_forward(char *serial_number, const char *adb_server_ip, unsigned short *adb_server_tcp_port,
1602         unsigned short local_tcp_port, unsigned short server_tcp_port) {
1603     socket_handle_t       sock;
1604     int                   result;
1605     static char           helpful_packet[PACKET_LENGTH];
1606     static const char    *adb_forward_template = "%s%s:forward:tcp:%05u;tcp:%05u";
1607
1608     sock = adb_connect(adb_server_ip, adb_server_tcp_port);
1609     if (sock == INVALID_SOCKET)
1610         return EXIT_CODE_INVALID_SOCKET_5;
1611
1612     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);
1613     if (result <= 0 || result > PACKET_LENGTH) {
1614         g_warning("Error while completing adb packet");
1615         closesocket(sock);
1616         return EXIT_CODE_BAD_SIZE_OF_ASSEMBLED_ADB_PACKET_12;
1617     }
1618
1619     result = adb_send(sock, helpful_packet);
1620     closesocket(sock);
1621
1622     return result;
1623 }
1624
1625 static int capture_android_bluetooth_external_parser(char *interface,
1626         char *fifo, const char *adb_server_ip, unsigned short *adb_server_tcp_port,
1627         unsigned short *bt_server_tcp_port, unsigned int bt_forward_socket, const char *bt_local_ip,
1628         unsigned short *bt_local_tcp_port) {
1629     struct extcap_dumper           extcap_dumper;
1630     static char                    buffer[PACKET_LENGTH];
1631     uint64_t                      *timestamp;
1632     char                          *packet = buffer + BLUEDROID_TIMESTAMP_SIZE - sizeof(own_pcap_bluetooth_h4_header); /* skip timestamp (8 bytes) and reuse its space for header */
1633     own_pcap_bluetooth_h4_header  *h4_header;
1634     guint8                        *payload = packet + sizeof(own_pcap_bluetooth_h4_header);
1635     const char                    *adb_tcp_bluedroid_external_parser_template = "tcp:%05u";
1636     socklen_t                      slen;
1637     gssize                         length;
1638     gssize                         used_buffer_length = 0;
1639     uint64_t                       ts;
1640     socket_handle_t                sock;
1641     struct sockaddr_in             server;
1642     int                            captured_length;
1643     char                          *serial_number;
1644     static unsigned int            id = 1;
1645     struct sockaddr_in             client;
1646
1647     SET_DATA(timestamp, value_u64, buffer);
1648     SET_DATA(h4_header, value_own_pcap_bluetooth_h4_header, packet);
1649
1650     extcap_dumper = extcap_dumper_open(fifo, EXTCAP_ENCAP_BLUETOOTH_H4_WITH_PHDR);
1651     serial_number = get_serial_from_interface(interface);
1652
1653     if (bt_forward_socket) {
1654         if ((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET) {
1655             g_warning("Cannot open system TCP socket: %s", strerror(errno));
1656             return EXIT_CODE_GENERIC;
1657         }
1658
1659         g_debug("Using config: Server TCP Port=%u, Local IP=%s, Local TCP Port=%u",
1660                     *bt_server_tcp_port, bt_local_ip, *bt_local_tcp_port);
1661
1662         if (*bt_local_tcp_port != 0) {
1663             int result;
1664
1665             result = adb_forward(serial_number, adb_server_ip, adb_server_tcp_port, *bt_local_tcp_port, *bt_server_tcp_port);
1666             g_debug("DO: adb forward tcp:%u (local) tcp:%u (remote) result=%i",
1667                         *bt_local_tcp_port, *bt_server_tcp_port, result);
1668         }
1669
1670         memset(&server, 0 , sizeof(server));
1671         server.sin_family = AF_INET;
1672         server.sin_port = GINT16_TO_BE(*bt_local_tcp_port);
1673         ws_inet_pton4(bt_local_ip, &(server.sin_addr.s_addr));
1674
1675         useSndTimeout(sock);
1676
1677         if (connect(sock, (struct sockaddr *) &server, sizeof(server)) == SOCKET_ERROR) {
1678             g_warning("<%s> Please check that adb daemon is running.", strerror(errno));
1679             closesocket(sock);
1680             return EXIT_CODE_GENERIC;
1681         }
1682
1683         slen = (socklen_t)sizeof(client);
1684         if (getsockname(sock, (struct sockaddr *) &client, &slen)) {
1685             g_warning("getsockname: %s", strerror(errno));
1686             closesocket(sock);
1687             return EXIT_CODE_GENERIC;
1688         }
1689
1690         if (slen != sizeof(client)) {
1691             g_warning("incorrect length");
1692             closesocket(sock);
1693             return EXIT_CODE_GENERIC;
1694         }
1695
1696         g_debug("Client port %u", GUINT16_FROM_BE(client.sin_port));
1697     } else {
1698         int  result;
1699
1700         sock = adb_connect_transport(adb_server_ip, adb_server_tcp_port, serial_number);
1701         if (sock == INVALID_SOCKET)
1702             return EXIT_CODE_INVALID_SOCKET_6;
1703
1704         result = g_snprintf((char *) buffer, PACKET_LENGTH, adb_tcp_bluedroid_external_parser_template, *bt_server_tcp_port);
1705         if (result <= 0 || result > PACKET_LENGTH) {
1706             g_warning("Error while completing adb packet");
1707             closesocket(sock);
1708             return EXIT_CODE_BAD_SIZE_OF_ASSEMBLED_ADB_PACKET_14;
1709         }
1710
1711         result = adb_send(sock, buffer);
1712         if (result) {
1713             g_warning("Error while forwarding adb port");
1714             closesocket(sock);
1715             return EXIT_CODE_GENERIC;
1716         }
1717     }
1718
1719     while (endless_loop) {
1720         errno = 0;
1721         length = recv(sock, buffer + used_buffer_length,  (int)(PACKET_LENGTH - used_buffer_length), 0);
1722         if (errno == EAGAIN
1723 #if EWOULDBLOCK != EAGAIN
1724             || errno == EWOULDBLOCK
1725 #endif
1726             ) {
1727             continue;
1728         }
1729         else if (errno != 0) {
1730             g_warning("ERROR capture: %s", strerror(errno));
1731             closesocket(sock);
1732             return EXIT_CODE_GENERIC;
1733         }
1734
1735         if (length <= 0) {
1736             if (bt_forward_socket) {
1737                 /* NOTE: Workaround... It seems that Bluedroid is slower and we can connect to socket that are not really ready... */
1738                 g_warning("Broken socket connection. Try reconnect.");
1739                 closesocket(sock);
1740
1741                 if ((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET) {
1742                     g_warning("%s", strerror(errno));
1743                     return EXIT_CODE_GENERIC;
1744                 }
1745
1746                 server.sin_family = AF_INET;
1747                 server.sin_port = GINT16_TO_BE(*bt_local_tcp_port);
1748                 ws_inet_pton4(bt_local_ip, &(server.sin_addr.s_addr));
1749
1750                 useSndTimeout(sock);
1751
1752                 if (connect(sock, (struct sockaddr *) &server, sizeof(server)) == SOCKET_ERROR) {
1753                     g_warning("ERROR reconnect: <%s> Please check that adb daemon is running.", strerror(errno));
1754                     closesocket(sock);
1755                     return EXIT_CODE_GENERIC;
1756                 }
1757             } else {
1758                 g_warning("Broken socket connection.");
1759                 closesocket(sock);
1760                 return EXIT_CODE_GENERIC;
1761             }
1762
1763             continue;
1764         }
1765
1766         used_buffer_length += length;
1767
1768         g_debug("Received: length=%"G_GSSIZE_FORMAT"", length);
1769
1770         while (((payload[BLUEDROID_H4_PACKET_TYPE] == BLUEDROID_H4_PACKET_TYPE_HCI_CMD || payload[BLUEDROID_H4_PACKET_TYPE] == BLUEDROID_H4_PACKET_TYPE_SCO) &&
1771                     used_buffer_length >= BLUEDROID_TIMESTAMP_SIZE + BLUEDROID_H4_SIZE + 2 + 1 &&
1772                     BLUEDROID_TIMESTAMP_SIZE + BLUEDROID_H4_SIZE + 2 + payload[BLUEDROID_H4_SIZE + 2] + 1 <= used_buffer_length) ||
1773                 (payload[BLUEDROID_H4_PACKET_TYPE] == BLUEDROID_H4_PACKET_TYPE_ACL &&
1774                     used_buffer_length >= BLUEDROID_TIMESTAMP_SIZE + BLUEDROID_H4_SIZE + 2 + 2 &&
1775                     BLUEDROID_TIMESTAMP_SIZE + BLUEDROID_H4_SIZE + 2 + payload[BLUEDROID_H4_SIZE + 2] + (payload[BLUEDROID_H4_SIZE + 2 + 1] << 8) + 2 <= used_buffer_length) ||
1776                 (payload[BLUEDROID_H4_PACKET_TYPE] == BLUEDROID_H4_PACKET_TYPE_SCO &&
1777                     used_buffer_length >= BLUEDROID_TIMESTAMP_SIZE + BLUEDROID_H4_SIZE + 2 + 1 &&
1778                     BLUEDROID_TIMESTAMP_SIZE + BLUEDROID_H4_SIZE + 2 + payload[BLUEDROID_H4_SIZE + 2] + 1 <= used_buffer_length) ||
1779                 (payload[BLUEDROID_H4_PACKET_TYPE] == BLUEDROID_H4_PACKET_TYPE_HCI_EVT &&
1780                     used_buffer_length >= BLUEDROID_TIMESTAMP_SIZE + BLUEDROID_H4_SIZE + 1 + 1 &&
1781                     BLUEDROID_TIMESTAMP_SIZE + BLUEDROID_H4_SIZE + 1 + payload[BLUEDROID_H4_SIZE + 1] + 1 <= used_buffer_length)) {
1782
1783             ts = GINT64_FROM_BE(*timestamp);
1784
1785             switch (payload[BLUEDROID_H4_PACKET_TYPE]) {
1786             case BLUEDROID_H4_PACKET_TYPE_HCI_CMD:
1787                 h4_header->direction = GINT32_TO_BE(BLUEDROID_DIRECTION_SENT);
1788
1789                 captured_length = (unsigned int)sizeof(own_pcap_bluetooth_h4_header) + payload[3] + 4;
1790
1791                 length = sizeof(own_pcap_bluetooth_h4_header) + BLUEDROID_H4_SIZE + 2 + 1 + payload[3];
1792
1793                 break;
1794             case BLUEDROID_H4_PACKET_TYPE_ACL:
1795                 h4_header->direction = (payload[2] & 0x80) ? GINT32_TO_BE(BLUEDROID_DIRECTION_RECV) : GINT32_TO_BE(BLUEDROID_DIRECTION_SENT);
1796
1797                 captured_length = (unsigned int)sizeof(own_pcap_bluetooth_h4_header) + payload[3] + (payload[3 + 1] << 8) + 5;
1798
1799                 length = sizeof(own_pcap_bluetooth_h4_header) + BLUEDROID_H4_SIZE + 2 + 2 + payload[3] + (gssize)(payload[3 + 1] << 8);
1800
1801                 break;
1802             case BLUEDROID_H4_PACKET_TYPE_SCO:
1803                 h4_header->direction = (payload[2] & 0x80) ? GINT32_TO_BE(BLUEDROID_DIRECTION_RECV) : GINT32_TO_BE(BLUEDROID_DIRECTION_SENT);
1804
1805                 captured_length = (unsigned int)sizeof(own_pcap_bluetooth_h4_header) + payload[3] + 4;
1806
1807                 length = sizeof(own_pcap_bluetooth_h4_header) + BLUEDROID_H4_SIZE + 2 + 1 + payload[3];
1808
1809                 break;
1810             case BLUEDROID_H4_PACKET_TYPE_HCI_EVT:
1811                 h4_header->direction = GINT32_TO_BE(BLUEDROID_DIRECTION_RECV);
1812
1813                 captured_length = (unsigned int)sizeof(own_pcap_bluetooth_h4_header) + payload[2] + 3;
1814
1815                 length = sizeof(own_pcap_bluetooth_h4_header) + BLUEDROID_H4_SIZE + 1 + 1 + payload[2];
1816
1817                 break;
1818             default:
1819                 g_warning("Invalid stream");
1820                 closesocket(sock);
1821                 return EXIT_CODE_GENERIC;
1822             }
1823
1824             g_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]);
1825             if (payload[BLUEDROID_H4_PACKET_TYPE] == BLUEDROID_H4_PACKET_TYPE_HCI_EVT)
1826                 g_debug("\t Packet: %02x %02x %02x", (unsigned int) payload[0], (unsigned int) payload[1], (unsigned int)payload[2]);
1827             id +=1;
1828
1829             ts -= BLUEDROID_TIMESTAMP_BASE;
1830
1831             endless_loop = extcap_dumper_dump(extcap_dumper, fifo, packet,
1832                     captured_length,
1833                     captured_length,
1834                     (uint32_t)(ts / 1000000),
1835                     ((uint32_t)(ts % 1000000)) * 1000);
1836
1837             used_buffer_length -= length - sizeof(own_pcap_bluetooth_h4_header) + BLUEDROID_TIMESTAMP_SIZE;
1838             if (used_buffer_length < 0) {
1839                 g_warning("Internal Negative used buffer length.");
1840                 closesocket(sock);
1841                 return EXIT_CODE_GENERIC;
1842             }
1843             memmove(buffer, packet + length, used_buffer_length);
1844         }
1845     }
1846
1847     closesocket(sock);
1848     return EXIT_CODE_SUCCESS;
1849 }
1850
1851 /*----------------------------------------------------------------------------*/
1852 /* Android Btsnoop Net */
1853 /*----------------------------------------------------------------------------*/
1854
1855 static int capture_android_bluetooth_btsnoop_net(char *interface, char *fifo,
1856         const char *adb_server_ip, unsigned short *adb_server_tcp_port) {
1857     struct extcap_dumper           extcap_dumper;
1858     static char                    packet[PACKET_LENGTH];
1859     gssize                         length;
1860     gssize                         used_buffer_length = 0;
1861     socket_handle_t                sock;
1862     const char                    *adb_tcp_btsnoop_net   = "tcp:8872";
1863     int                            result;
1864     char                          *serial_number;
1865     uint64_t                       ts;
1866     static const uint64_t          BTSNOOP_TIMESTAMP_BASE = G_GUINT64_CONSTANT(0x00dcddb30f2f8000);
1867     uint32_t                      *reported_length;
1868     uint32_t                      *captured_length;
1869     uint32_t                      *flags;
1870 /*    uint32_t                     *cumulative_dropped_packets; */
1871     uint64_t                      *timestamp;
1872     char                          *payload                     =  packet + sizeof(own_pcap_bluetooth_h4_header) + 24;
1873     own_pcap_bluetooth_h4_header  *h4_header;
1874
1875     SET_DATA(reported_length, value_u32, packet + sizeof(own_pcap_bluetooth_h4_header) + 0);
1876     SET_DATA(captured_length, value_u32, packet + sizeof(own_pcap_bluetooth_h4_header) + 4);
1877     SET_DATA(flags, value_u32, packet + sizeof(own_pcap_bluetooth_h4_header) + 8);
1878 /*    SET_DATA(cumulative_dropped_packets, value_u32, packet + sizeof(own_pcap_bluetooth_h4_header) + 12); */
1879     SET_DATA(timestamp, value_u64, packet + sizeof(own_pcap_bluetooth_h4_header) + 16);
1880     SET_DATA(h4_header, value_own_pcap_bluetooth_h4_header, payload - sizeof(own_pcap_bluetooth_h4_header));
1881
1882     extcap_dumper = extcap_dumper_open(fifo, EXTCAP_ENCAP_BLUETOOTH_H4_WITH_PHDR);
1883     serial_number = get_serial_from_interface(interface);
1884     sock = adb_connect_transport(adb_server_ip, adb_server_tcp_port, serial_number);
1885     if (sock == INVALID_SOCKET)
1886         return EXIT_CODE_INVALID_SOCKET_7;
1887
1888     result = adb_send(sock, adb_tcp_btsnoop_net);
1889     if (result) {
1890         g_warning("Error while sending command <%s>", adb_tcp_btsnoop_net);
1891         closesocket(sock);
1892         return EXIT_CODE_ERROR_WHILE_SENDING_ADB_PACKET_2;
1893     }
1894
1895     /* Read "btsnoop" header - 16 bytes */
1896     while (used_buffer_length < 16) {
1897         length = recv(sock, packet + used_buffer_length,  (int)(PACKET_LENGTH - used_buffer_length), 0);
1898
1899         if (length <= 0) {
1900             g_warning("Broken socket connection.");
1901             closesocket(sock);
1902             return EXIT_CODE_GENERIC;
1903         }
1904
1905         used_buffer_length += length;
1906     }
1907     if (used_buffer_length > 16)
1908         memmove(packet, packet + 16, used_buffer_length - 16);
1909
1910     used_buffer_length = 0;
1911
1912     while (endless_loop) {
1913         errno = 0;
1914         length = recv(sock, packet + used_buffer_length + sizeof(own_pcap_bluetooth_h4_header),
1915                 (int)(PACKET_LENGTH - sizeof(own_pcap_bluetooth_h4_header) - used_buffer_length), 0);
1916         if (errno == EAGAIN
1917 #if EWOULDBLOCK != EAGAIN
1918             || errno == EWOULDBLOCK
1919 #endif
1920             ) {
1921             continue;
1922         }
1923         else if (errno != 0) {
1924             g_warning("ERROR capture: %s", strerror(errno));
1925             closesocket(sock);
1926             return EXIT_CODE_GENERIC;
1927         }
1928
1929         if (length <= 0) {
1930             g_warning("Broken socket connection.");
1931             closesocket(sock);
1932             return EXIT_CODE_GENERIC;
1933         }
1934
1935         used_buffer_length += length;
1936
1937         while (used_buffer_length >= 24 &&
1938                 used_buffer_length >= (int) (24 + GINT32_FROM_BE(*captured_length))) {
1939             gint32 direction;
1940
1941             ts = GINT64_FROM_BE(*timestamp);
1942             ts -= BTSNOOP_TIMESTAMP_BASE;
1943
1944             direction = GINT32_FROM_BE(*flags) & 0x01;
1945             h4_header->direction = GINT32_TO_BE(direction);
1946
1947             endless_loop = extcap_dumper_dump(extcap_dumper, fifo,
1948                     payload - sizeof(own_pcap_bluetooth_h4_header),
1949                     GINT32_FROM_BE(*captured_length) + sizeof(own_pcap_bluetooth_h4_header),
1950                     GINT32_FROM_BE(*reported_length) + sizeof(own_pcap_bluetooth_h4_header),
1951                     (uint32_t)(ts / 1000000),
1952                     ((uint32_t)(ts % 1000000)) * 1000);
1953
1954             used_buffer_length -= 24 + GINT32_FROM_BE(*captured_length);
1955             if (used_buffer_length < 0) {
1956                 g_warning("Internal Negative used buffer length.");
1957                 closesocket(sock);
1958                 return EXIT_CODE_GENERIC;
1959             }
1960
1961             if  (used_buffer_length > 0)
1962                 memmove(packet + sizeof(own_pcap_bluetooth_h4_header), payload + GINT32_FROM_BE(*captured_length), used_buffer_length);
1963         }
1964     }
1965
1966     closesocket(sock);
1967     return EXIT_CODE_SUCCESS;
1968 }
1969
1970 /*----------------------------------------------------------------------------*/
1971 /* Android Logcat Text*/
1972 /*----------------------------------------------------------------------------*/
1973
1974
1975 static int capture_android_logcat_text(char *interface, char *fifo,
1976         const char *adb_server_ip, unsigned short *adb_server_tcp_port,
1977         int logcat_ignore_log_buffer, const char *logcat_custom_parameter) {
1978     struct extcap_dumper        extcap_dumper;
1979     static char                 packet[PACKET_LENGTH];
1980     gssize                      length;
1981     size_t                      used_buffer_length = 0;
1982     socket_handle_t             sock;
1983     const char                 *protocol_name;
1984     size_t                      exported_pdu_headers_size = 0;
1985     struct exported_pdu_header  exported_pdu_header_protocol_normal;
1986     struct exported_pdu_header *exported_pdu_header_protocol;
1987     struct exported_pdu_header  exported_pdu_header_end = {0, 0};
1988     static const char          *wireshark_protocol_logcat_text = "logcat_text_threadtime";
1989     const char                 *adb_logcat_template = "shell:export ANDROID_LOG_TAGS=\"\" ; exec logcat -v threadtime%s%s %s";
1990     char                       *serial_number = NULL;
1991     int                         result;
1992     char                       *pos;
1993     const char                 *logcat_buffer;
1994     const char                 *logcat_log_buffer;
1995
1996     extcap_dumper = extcap_dumper_open(fifo, EXTCAP_ENCAP_WIRESHARK_UPPER_PDU);
1997
1998     exported_pdu_header_protocol_normal.tag = GUINT16_TO_BE(WIRESHARK_UPPER_PDU_TAG_DISSECTOR_NAME);
1999     exported_pdu_header_protocol_normal.length = GUINT16_TO_BE(strlen(wireshark_protocol_logcat_text) + 2);
2000
2001     serial_number = get_serial_from_interface(interface);
2002     sock = adb_connect_transport(adb_server_ip, adb_server_tcp_port, serial_number);
2003     if (sock == INVALID_SOCKET)
2004         return EXIT_CODE_INVALID_SOCKET_8;
2005
2006     if (is_specified_interface(interface, INTERFACE_ANDROID_LOGCAT_MAIN) || is_specified_interface(interface, INTERFACE_ANDROID_LOGCAT_TEXT_MAIN))
2007         logcat_buffer = " -b main";
2008     else if (is_specified_interface(interface, INTERFACE_ANDROID_LOGCAT_SYSTEM) || is_specified_interface(interface, INTERFACE_ANDROID_LOGCAT_TEXT_SYSTEM))
2009         logcat_buffer = " -b system";
2010     else if (is_specified_interface(interface, INTERFACE_ANDROID_LOGCAT_RADIO) || is_specified_interface(interface, INTERFACE_ANDROID_LOGCAT_TEXT_RADIO))
2011         logcat_buffer = " -b radio";
2012     else if (is_specified_interface(interface, INTERFACE_ANDROID_LOGCAT_EVENTS) || is_specified_interface(interface, INTERFACE_ANDROID_LOGCAT_TEXT_EVENTS))
2013         logcat_buffer = " -b events";
2014     else if (is_specified_interface(interface, INTERFACE_ANDROID_LOGCAT_TEXT_CRASH))
2015         logcat_buffer = " -b crash";
2016     else {
2017         g_warning("Unknown interface: <%s>", interface);
2018         closesocket(sock);
2019         return EXIT_CODE_GENERIC;
2020     }
2021
2022     if (logcat_ignore_log_buffer)
2023         logcat_log_buffer = " -T 1";
2024     else
2025         logcat_log_buffer = "";
2026
2027     if (!logcat_custom_parameter)
2028         logcat_custom_parameter = "";
2029
2030     result = g_snprintf((char *) packet, PACKET_LENGTH, adb_logcat_template, logcat_buffer, logcat_log_buffer, logcat_custom_parameter);
2031     if (result <= 0 || result > PACKET_LENGTH) {
2032         g_warning("Error while completing adb packet");
2033         closesocket(sock);
2034         return EXIT_CODE_BAD_SIZE_OF_ASSEMBLED_ADB_PACKET_17;
2035     }
2036
2037     result = adb_send(sock, packet);
2038     if (result) {
2039         g_warning("Error while sending command <%s>", packet);
2040         closesocket(sock);
2041         return EXIT_CODE_ERROR_WHILE_SENDING_ADB_PACKET_3;
2042     }
2043
2044     protocol_name = wireshark_protocol_logcat_text;
2045     exported_pdu_header_protocol = &exported_pdu_header_protocol_normal;
2046
2047     memcpy(packet, exported_pdu_header_protocol, sizeof(struct exported_pdu_header));
2048     exported_pdu_headers_size += sizeof(struct exported_pdu_header);
2049
2050     memcpy(packet + exported_pdu_headers_size, protocol_name, GUINT16_FROM_BE(exported_pdu_header_protocol->length) - 2);
2051     exported_pdu_headers_size += GUINT16_FROM_BE(exported_pdu_header_protocol->length);
2052
2053     packet[exported_pdu_headers_size - 1] = 0;
2054     packet[exported_pdu_headers_size - 2] = 0;
2055
2056     memcpy(packet + exported_pdu_headers_size, &exported_pdu_header_end, sizeof(struct exported_pdu_header));
2057     exported_pdu_headers_size += sizeof(struct exported_pdu_header) + GUINT16_FROM_BE(exported_pdu_header_end.length);
2058
2059     used_buffer_length = 0;
2060     while (endless_loop) {
2061         errno = 0;
2062         length = recv(sock, packet + exported_pdu_headers_size + used_buffer_length,  (int)(PACKET_LENGTH - exported_pdu_headers_size - used_buffer_length), 0);
2063         if (errno == EAGAIN
2064 #if EWOULDBLOCK != EAGAIN
2065             || errno == EWOULDBLOCK
2066 #endif
2067             ) {
2068             continue;
2069         }
2070         else if (errno != 0) {
2071             g_warning("ERROR capture: %s", strerror(errno));
2072             closesocket(sock);
2073             return EXIT_CODE_GENERIC;
2074         }
2075
2076         if (length <= 0) {
2077             g_warning("Broken socket connection. Try reconnect.");
2078             closesocket(sock);
2079             return EXIT_CODE_GENERIC;
2080         }
2081
2082         used_buffer_length += length;
2083
2084         while (used_buffer_length > 0 && (pos = (char *) memchr(packet + exported_pdu_headers_size, '\n', used_buffer_length))) {
2085             int        ms;
2086             struct tm* date;
2087             time_t     seconds;
2088             time_t     secs = 0;
2089             int        nsecs = 0;
2090             time_t     t;
2091
2092             length = (gssize)(pos - packet) + 1;
2093
2094             t = time(NULL);
2095             date = localtime(&t);
2096             if (!date)
2097                 continue;
2098             if (6 == sscanf(packet + exported_pdu_headers_size, "%d-%d %d:%d:%d.%d", &date->tm_mon, &date->tm_mday, &date->tm_hour,
2099                             &date->tm_min, &date->tm_sec, &ms)) {
2100                 date->tm_mon -= 1;
2101                 seconds = mktime(date);
2102                 secs = (time_t) seconds;
2103                 nsecs = (int) (ms * 1e6);
2104             }
2105
2106             endless_loop = extcap_dumper_dump(extcap_dumper, fifo, packet,
2107                     length,
2108                     length,
2109                     secs, nsecs);
2110
2111             memmove(packet + exported_pdu_headers_size, packet + length, used_buffer_length + exported_pdu_headers_size - length);
2112             used_buffer_length -= length - exported_pdu_headers_size;
2113         }
2114     }
2115
2116     closesocket(sock);
2117     return EXIT_CODE_SUCCESS;
2118 }
2119
2120 /*----------------------------------------------------------------------------*/
2121 /* Android Logger / Logcat */
2122 /*----------------------------------------------------------------------------*/
2123
2124 static int capture_android_logcat(char *interface, char *fifo,
2125         const char *adb_server_ip, unsigned short *adb_server_tcp_port) {
2126     struct extcap_dumper        extcap_dumper;
2127     static char                 packet[PACKET_LENGTH];
2128     gssize                      length;
2129     size_t                      used_buffer_length = 0;
2130     socket_handle_t             sock;
2131     const char                 *protocol_name;
2132     size_t                      exported_pdu_headers_size = 0;
2133     struct exported_pdu_header  exported_pdu_header_protocol_events;
2134     struct exported_pdu_header  exported_pdu_header_protocol_normal;
2135     struct exported_pdu_header *exported_pdu_header_protocol;
2136     struct exported_pdu_header  exported_pdu_header_end = {0, 0};
2137     static const char          *wireshark_protocol_logcat = "logcat";
2138     static const char          *wireshark_protocol_logcat_events = "logcat_events";
2139     const char                 *adb_command;
2140     uint16_t                   *payload_length;
2141     uint16_t                   *try_header_size;
2142     uint32_t                   *timestamp_secs;
2143     uint32_t                   *timestamp_nsecs;
2144     uint16_t                    header_size;
2145     int                         result;
2146     char                       *serial_number = NULL;
2147
2148     extcap_dumper = extcap_dumper_open(fifo, EXTCAP_ENCAP_WIRESHARK_UPPER_PDU);
2149
2150     exported_pdu_header_protocol_events.tag = GUINT16_TO_BE(WIRESHARK_UPPER_PDU_TAG_DISSECTOR_NAME);
2151     exported_pdu_header_protocol_events.length = GUINT16_TO_BE(strlen(wireshark_protocol_logcat_events) + 2);
2152
2153     exported_pdu_header_protocol_normal.tag = GUINT16_TO_BE(WIRESHARK_UPPER_PDU_TAG_DISSECTOR_NAME);
2154     exported_pdu_header_protocol_normal.length = GUINT16_TO_BE(strlen(wireshark_protocol_logcat) + 2);
2155
2156     serial_number = get_serial_from_interface(interface);
2157     sock = adb_connect_transport(adb_server_ip, adb_server_tcp_port, serial_number);
2158     if (sock == INVALID_SOCKET)
2159         return EXIT_CODE_INVALID_SOCKET_9;
2160
2161     adb_command = interface_to_logbuf(interface);
2162     if (!adb_command) {
2163         g_warning("Unknown interface: <%s>", interface);
2164         closesocket(sock);
2165         return EXIT_CODE_GENERIC;
2166     }
2167
2168     result = adb_send(sock, adb_command);
2169     if (result) {
2170         g_warning("Error while sending command <%s>", adb_command);
2171         closesocket(sock);
2172         return EXIT_CODE_ERROR_WHILE_SENDING_ADB_PACKET_4;
2173     }
2174
2175     if (is_specified_interface(interface, INTERFACE_ANDROID_LOGCAT_EVENTS))
2176     {
2177         protocol_name = wireshark_protocol_logcat_events;
2178         exported_pdu_header_protocol = &exported_pdu_header_protocol_events;
2179     } else {
2180         protocol_name = wireshark_protocol_logcat;
2181         exported_pdu_header_protocol = &exported_pdu_header_protocol_normal;
2182     }
2183
2184     memcpy(packet, exported_pdu_header_protocol, sizeof(struct exported_pdu_header));
2185     exported_pdu_headers_size += sizeof(struct exported_pdu_header);
2186
2187     memcpy(packet + exported_pdu_headers_size, protocol_name, GUINT16_FROM_BE(exported_pdu_header_protocol->length) - 2);
2188     exported_pdu_headers_size += GUINT16_FROM_BE(exported_pdu_header_protocol->length);
2189
2190     packet[exported_pdu_headers_size - 1] = 0;
2191     packet[exported_pdu_headers_size - 2] = 0;
2192
2193     memcpy(packet + exported_pdu_headers_size, &exported_pdu_header_end, sizeof(struct exported_pdu_header));
2194     exported_pdu_headers_size += sizeof(struct exported_pdu_header) + GUINT16_FROM_BE(exported_pdu_header_end.length);
2195
2196     SET_DATA(payload_length,  value_u16, packet + exported_pdu_headers_size +  0);
2197     SET_DATA(try_header_size, value_u16, packet + exported_pdu_headers_size +  2);
2198     SET_DATA(timestamp_secs,  value_u32, packet + exported_pdu_headers_size + 12);
2199     SET_DATA(timestamp_nsecs, value_u32, packet + exported_pdu_headers_size + 16);
2200
2201     while (endless_loop) {
2202         errno = 0;
2203         length = recv(sock, packet + exported_pdu_headers_size + used_buffer_length, (int)(PACKET_LENGTH - exported_pdu_headers_size - used_buffer_length), 0);
2204         if (errno == EAGAIN
2205 #if EWOULDBLOCK != EAGAIN
2206             || errno == EWOULDBLOCK
2207 #endif
2208             ) {
2209             continue;
2210         }
2211         else if (errno != 0) {
2212             g_warning("ERROR capture: %s", strerror(errno));
2213             closesocket(sock);
2214             return EXIT_CODE_GENERIC;
2215         }
2216
2217         if (length <= 0) {
2218             while (endless_loop) {
2219                 g_warning("Broken socket connection. Try reconnect.");
2220                 used_buffer_length = 0;
2221                 closesocket(sock);
2222
2223                 sock = adb_connect_transport(adb_server_ip, adb_server_tcp_port, serial_number);
2224                 if (sock == INVALID_SOCKET)
2225                     return EXIT_CODE_INVALID_SOCKET_10;
2226
2227                 result = adb_send(sock, adb_command);
2228                 if (result) {
2229                     g_warning("WARNIG: Error while sending command <%s>", adb_command);
2230                     continue;
2231                 }
2232
2233                 break;
2234             }
2235         }
2236
2237         used_buffer_length += length + exported_pdu_headers_size;
2238
2239         if (*try_header_size != 24)
2240             header_size = 20;
2241         else
2242             header_size = *try_header_size;
2243
2244         length = (*payload_length) + header_size + (gssize)exported_pdu_headers_size;
2245
2246         while (used_buffer_length >= exported_pdu_headers_size + header_size && (size_t)length <= used_buffer_length) {
2247             endless_loop = extcap_dumper_dump(extcap_dumper, fifo, packet,
2248                     length,
2249                     length,
2250                     *timestamp_secs, *timestamp_nsecs);
2251
2252             memmove(packet + exported_pdu_headers_size, packet + length, used_buffer_length - length);
2253             used_buffer_length -= length;
2254             used_buffer_length += exported_pdu_headers_size;
2255
2256
2257             length = (*payload_length) + header_size + (gssize)exported_pdu_headers_size;
2258
2259             if (*try_header_size != 24)
2260                 header_size = 20;
2261             else
2262                 header_size = *try_header_size;
2263         }
2264         used_buffer_length -= exported_pdu_headers_size;
2265     }
2266
2267     closesocket(sock);
2268
2269     return EXIT_CODE_SUCCESS;
2270 }
2271
2272 /* Translate tcpdump data link type strings to EXTCAP_ENCAP_ types
2273  * For info about available data link types see:
2274  * http://www.tcpdump.org/linktypes.html
2275  */
2276 static int linktype_to_extcap_encap(const char* linktype)
2277 {
2278     struct dlt_encap {
2279         int extcap_encap;
2280         const char* const dlt;
2281     };
2282     const struct dlt_encap lookup[] = {
2283         { EXTCAP_ENCAP_LINUX_SLL, "LINUX_SLL" },
2284         { EXTCAP_ENCAP_ETHERNET, "EN10MB" },
2285         { EXTCAP_ENCAP_IEEE802_11_RADIO, "IEEE802_11_RADIO" },
2286         { EXTCAP_ENCAP_NETLINK, "NETLINK" },
2287         { -1, NULL }
2288     };
2289     int i;
2290     int ret = EXTCAP_ENCAP_ETHERNET;
2291
2292     if (!linktype)
2293         return ret;
2294     for (i = 0; lookup[i].dlt; i++) {
2295         if (!strcmp(lookup[i].dlt, linktype)) {
2296             ret = lookup[i].extcap_encap;
2297         }
2298     }
2299     return ret;
2300 }
2301
2302
2303 /*----------------------------------------------------------------------------*/
2304 /* Android Wifi Tcpdump                                                       */
2305 /* The Tcpdump sends data in pcap format. So for using the extcap_dumper we   */
2306 /* need to unpack the pcap and then send the packet data to the dumper.       */
2307 /*----------------------------------------------------------------------------*/
2308 static int capture_android_tcpdump(char *interface, char *fifo,
2309         const char *adb_server_ip, unsigned short *adb_server_tcp_port) {
2310     static const char                       *const adb_shell_tcpdump_format = "shell,raw:tcpdump -n -s 0 -u -i %s -w -";
2311     static const char                       *const adb_shell_legacy_tcpdump_format = "shell:tcpdump -n -s 0 -u -i %s -w -";
2312     static const char                       *const regex_interface = INTERFACE_ANDROID_TCPDUMP "-(?<iface>.*?)-(?<serial>.*)";
2313     static const char                       *const regex_linktype = "tcpdump: listening on .*?, link-type (?<linktype>.*?) ";
2314     struct extcap_dumper                     extcap_dumper;
2315     static char                              data[PACKET_LENGTH];
2316     gssize                                   length;
2317     gssize                                   used_buffer_length =  0;
2318     gssize                                   filter_buffer_length = 0;
2319     gssize                                   frame_length=0;
2320     socket_handle_t                          sock;
2321     gint                                     result;
2322     char                                    *iface = NULL;
2323     char                                    *serial_number = NULL;
2324     static char                              filter_buffer[PACKET_LENGTH];
2325     gint                                     device_endiness = G_LITTLE_ENDIAN;
2326     gboolean                                 global_header_skipped=FALSE;
2327     pcaprec_hdr_t                            p_header;
2328     char                                    *linktype = NULL;
2329     GRegex                                  *regex = NULL;
2330     GError                                  *err = NULL;
2331     GMatchInfo                              *match = NULL;
2332     char                                     tcpdump_cmd[80];
2333     gboolean                                 pty_mode = FALSE;
2334
2335     regex = g_regex_new(regex_interface, (GRegexCompileFlags)0, (GRegexMatchFlags)0, &err);
2336     if (!regex) {
2337         g_warning("Failed to compile regex for tcpdump interface");
2338         return EXIT_CODE_GENERIC;
2339     }
2340
2341     g_regex_match(regex, interface, (GRegexMatchFlags)0, &match);
2342     if (!g_match_info_matches(match)) {
2343         g_warning("Failed to determine iface name and serial number");
2344         g_regex_unref(regex);
2345         return EXIT_CODE_GENERIC;
2346     }
2347
2348     iface = g_match_info_fetch_named(match, "iface");
2349     serial_number = g_match_info_fetch_named(match, "serial");
2350     g_match_info_free(match);
2351     g_regex_unref(regex);
2352
2353     /* First check for the device if it is connected or not */
2354     sock = adb_connect_transport(adb_server_ip, adb_server_tcp_port, serial_number);
2355     if (sock == INVALID_SOCKET) {
2356         g_free(iface);
2357         g_free(serial_number);
2358         return EXIT_CODE_INVALID_SOCKET_11;
2359     }
2360
2361     /* Try the new raw (non-PTY) shell protocol first */
2362     g_snprintf(tcpdump_cmd, sizeof(tcpdump_cmd), adb_shell_tcpdump_format, iface);
2363     result = adb_send(sock, tcpdump_cmd);
2364     if (result) {
2365         g_debug("Target does not support raw shell protocol");
2366         closesocket(sock);
2367
2368         /* Fall back to the old PTY shell */
2369         sock = adb_connect_transport(adb_server_ip, adb_server_tcp_port, serial_number);
2370         if (sock == INVALID_SOCKET) {
2371             g_free(iface);
2372             g_free(serial_number);
2373             return EXIT_CODE_INVALID_SOCKET_12;
2374         }
2375
2376         pty_mode = TRUE;
2377         g_snprintf(tcpdump_cmd, sizeof(tcpdump_cmd), adb_shell_legacy_tcpdump_format, iface);
2378         result = adb_send(sock, tcpdump_cmd);
2379     }
2380     if (result) {
2381         g_warning("Error while setting adb transport");
2382         closesocket(sock);
2383         return EXIT_CODE_GENERIC;
2384     }
2385
2386     g_free(iface);
2387     g_free(serial_number);
2388
2389     regex = g_regex_new(regex_linktype, (GRegexCompileFlags)0, (GRegexMatchFlags)0, &err);
2390     if (!regex) {
2391         g_warning("Failed to compile regex for tcpdump data link type matching");
2392         closesocket(sock);
2393         return EXIT_CODE_GENERIC;
2394     }
2395
2396     while (endless_loop) {
2397         char *i_position;
2398         errno = 0;
2399         length = recv(sock, data + used_buffer_length, (int)(PACKET_LENGTH - used_buffer_length), 0);
2400         if (errno == EAGAIN
2401 #if EWOULDBLOCK != EAGAIN
2402             || errno == EWOULDBLOCK
2403 #endif
2404             ) {
2405             continue;
2406         }
2407         else if (errno != 0) {
2408             g_warning("ERROR capture: %s", strerror(errno));
2409             closesocket(sock);
2410             g_regex_unref(regex);
2411             return EXIT_CODE_GENERIC;
2412         }
2413
2414         if (length <= 0) {
2415             g_warning("Broken socket connection.");
2416             closesocket(sock);
2417             g_regex_unref(regex);
2418             return EXIT_CODE_GENERIC;
2419         }
2420
2421         used_buffer_length += length;
2422
2423         /*
2424          * Checking for the starting for the pcap global header using the magic number
2425          */
2426         if (used_buffer_length > 4) {
2427             guint * magic_number;
2428             magic_number= (guint *)data;
2429             if (*magic_number == 0xd4c3b2a1 || *magic_number == 0xa1b2c3d4) {
2430                 if (data[0] == (char)0xd4){
2431                     device_endiness = G_LITTLE_ENDIAN;
2432                 }
2433                 else {
2434                     device_endiness = G_BIG_ENDIAN;
2435                 }
2436                 break;
2437             }
2438         }
2439
2440         g_regex_match(regex, data, (GRegexMatchFlags)0, &match);
2441         if (g_match_info_matches(match)) {
2442             g_free(linktype);
2443             linktype = g_match_info_fetch_named(match, "linktype");
2444         }
2445         g_match_info_free(match);
2446         i_position = (char *) memchr(data, '\n', used_buffer_length);
2447         if (i_position && i_position < data + used_buffer_length) {
2448             memmove(data, i_position + 1 , used_buffer_length - (i_position + 1 - data));
2449             used_buffer_length = used_buffer_length - (gssize) (i_position + 1 - data);
2450         }
2451     }
2452     g_regex_unref(regex);
2453     extcap_dumper = extcap_dumper_open(fifo, linktype_to_extcap_encap(linktype));
2454     g_free(linktype);
2455
2456     filter_buffer_length=0;
2457     while (endless_loop) {
2458         gssize i = 0,read_offset,j=0;
2459
2460         /*
2461          * Before Android 7 adb runs tcpdump in a shell/pseudoterminal and the PTY layer on the target converts
2462          * all \n to \r\n. In that case we need to undo this by changing all \r\n (0x0d0a) back to \n (0x0a).
2463          */
2464         for (i = 0; i < (used_buffer_length - 1); i++) {
2465             if (pty_mode && data[i] == 0x0d && data[i + 1] == 0x0a) {
2466                 i++;
2467             }
2468             filter_buffer[filter_buffer_length++] = data[i];
2469         }
2470
2471         /* Put the last characters in the start if it is still left in buffer.*/
2472         for (j=0; i < used_buffer_length; i++,j++) {
2473             data[j] = data[i];
2474         }
2475         used_buffer_length = j;
2476         if (global_header_skipped==FALSE && filter_buffer_length >= PCAP_GLOBAL_HEADER_LENGTH) {
2477             /*Skip the Global pcap header*/
2478             filter_buffer_length -= PCAP_GLOBAL_HEADER_LENGTH;
2479
2480             /*Move the remaining content from start*/
2481             memmove(filter_buffer , filter_buffer + PCAP_GLOBAL_HEADER_LENGTH , filter_buffer_length);
2482             global_header_skipped = TRUE;
2483         }
2484         else if (global_header_skipped && filter_buffer_length > PCAP_RECORD_HEADER_LENGTH) {
2485             read_offset=0;
2486             while (filter_buffer_length > PCAP_RECORD_HEADER_LENGTH) {
2487                 gchar *packet;
2488                 packet = filter_buffer + read_offset;
2489                  /*
2490                  * This fills the pcap header info based upon the endianess of the machine and android device.
2491                  * If the endianess are different, pcap header bytes received from the android device are swapped
2492                  * to be read properly by the machine else pcap header bytes are taken as it is.
2493                  */
2494                 if (device_endiness == G_BYTE_ORDER) {
2495                     p_header = *((pcaprec_hdr_t*)packet);
2496                 }
2497                 else {
2498                     p_header.ts_sec = GUINT32_SWAP_LE_BE(*((guint32*)packet));
2499                     p_header.ts_usec = GUINT32_SWAP_LE_BE(*(guint32*)(packet +4));
2500                     p_header.incl_len = GUINT32_SWAP_LE_BE(*(guint32*)(packet +8));
2501                     p_header.orig_len = GUINT32_SWAP_LE_BE(*(guint32*)(packet +12));
2502                 }
2503
2504                 if ((gssize)(p_header.incl_len + PCAP_RECORD_HEADER_LENGTH) <= filter_buffer_length) {
2505
2506                     /*
2507                      * It was observed that some times tcpdump reports the length of packet as '0' and that leads to the
2508                      * ( Warn Error "Less data was read than was expected" while reading )
2509                      * So to avoid this error we are checking for length of packet before passing it to dumper.
2510                      */
2511                     if (p_header.incl_len > 0) {
2512                         endless_loop = extcap_dumper_dump(extcap_dumper, fifo, filter_buffer + read_offset+ PCAP_RECORD_HEADER_LENGTH,
2513                         p_header.incl_len , p_header.orig_len , p_header.ts_sec , p_header.ts_usec);
2514                     }
2515                     frame_length = p_header.incl_len + PCAP_RECORD_HEADER_LENGTH;
2516
2517                     /*update the offset value for the next packet*/
2518                     filter_buffer_length -= frame_length;
2519                     read_offset += frame_length;
2520                 }
2521                 else {
2522                     /*The complete packet has not yet received*/
2523                     break;
2524                 }
2525             }
2526             if (read_offset!=0) {
2527                 /*Move the rest of the filter  data to the beginning of the filter_buffer */
2528                 memmove(filter_buffer, filter_buffer + read_offset , filter_buffer_length);
2529             }
2530         }
2531
2532         /*Get the data from the tcpdump process running in the android device*/
2533         while (endless_loop) {
2534             errno = 0;
2535             length = recv(sock, data + used_buffer_length, (int)(PACKET_LENGTH -(used_buffer_length + filter_buffer_length)), 0);
2536             if (errno == EAGAIN
2537 #if EWOULDBLOCK != EAGAIN
2538                 || errno == EWOULDBLOCK
2539 #endif
2540                 ) {
2541                 continue;
2542             }
2543             else if (errno != 0) {
2544                 g_warning("ERROR capture: %s", strerror(errno));
2545                 closesocket(sock);
2546                 return EXIT_CODE_GENERIC;
2547             }
2548
2549             if (length <= 0) {
2550                 g_warning("Broken socket connection.");
2551                 closesocket(sock);
2552                 return EXIT_CODE_GENERIC;
2553             }
2554
2555             if ((used_buffer_length += length) > 1) {
2556                 break;
2557             }
2558         }
2559     }
2560
2561     closesocket(sock);
2562     return EXIT_CODE_SUCCESS;
2563 }
2564
2565 int main(int argc, char **argv) {
2566     int              ret = EXIT_CODE_GENERIC;
2567     int              option_idx = 0;
2568     int              result;
2569     const char      *adb_server_ip       = NULL;
2570     unsigned short  *adb_server_tcp_port = NULL;
2571     unsigned int     logcat_text   = 0;
2572     unsigned int     logcat_ignore_log_buffer = 0;
2573     const char      *logcat_custom_parameter   = NULL;
2574     const char      *default_adb_server_ip = "127.0.0.1";
2575     unsigned short   default_adb_server_tcp_port = 5037;
2576     unsigned short   local_adb_server_tcp_port;
2577     unsigned short   local_bt_server_tcp_port;
2578     unsigned short   local_bt_local_tcp_port;
2579     unsigned short  *bt_server_tcp_port  = NULL;
2580     unsigned int     bt_forward_socket   = 0;
2581     const char      *bt_local_ip         = NULL;
2582     unsigned short  *bt_local_tcp_port   = NULL;
2583     unsigned short   default_bt_server_tcp_port = 4330;
2584     const char      *default_bt_local_ip = "127.0.0.1";
2585     unsigned short   default_bt_local_tcp_port  = 4330;
2586     extcap_parameters * extcap_conf = NULL;
2587     char            *help_url;
2588     char            *help_header = NULL;
2589
2590 #ifdef _WIN32
2591     WSADATA          wsaData;
2592
2593     attach_parent_console();
2594 #endif  /* _WIN32 */
2595
2596     cmdarg_err_init(failure_warning_message, failure_warning_message);
2597
2598     extcap_conf = g_new0(extcap_parameters, 1);
2599
2600     help_url = data_file_url("androiddump.html");
2601     extcap_base_set_util_info(extcap_conf, argv[0], ANDROIDDUMP_VERSION_MAJOR, ANDROIDDUMP_VERSION_MINOR,
2602         ANDROIDDUMP_VERSION_RELEASE, help_url);
2603     g_free(help_url);
2604
2605     help_header = g_strdup_printf(
2606         " %s --extcap-interfaces [--adb-server-ip=<arg>] [--adb-server-tcp-port=<arg>]\n"
2607         " %s --extcap-interface=INTERFACE --extcap-dlts\n"
2608         " %s --extcap-interface=INTERFACE --extcap-config\n"
2609         " %s --extcap-interface=INTERFACE --fifo=PATH_FILENAME --capture\n"
2610         "\nINTERFACE has the form TYPE-DEVICEID:\n"
2611         "\t""For example: "INTERFACE_ANDROID_BLUETOOTH_BTSNOOP_NET"-W3D7N15C29005648""\n"
2612         "\n"
2613         "\tTYPE is one of:\n"
2614         "\t"INTERFACE_ANDROID_LOGCAT_MAIN"\n"
2615         "\t"INTERFACE_ANDROID_LOGCAT_SYSTEM"\n"
2616         "\t"INTERFACE_ANDROID_LOGCAT_RADIO"\n"
2617         "\t"INTERFACE_ANDROID_LOGCAT_EVENTS"\n"
2618         "\t"INTERFACE_ANDROID_LOGCAT_TEXT_MAIN"\n"
2619         "\t"INTERFACE_ANDROID_LOGCAT_TEXT_SYSTEM"\n"
2620         "\t"INTERFACE_ANDROID_LOGCAT_TEXT_RADIO"\n"
2621         "\t"INTERFACE_ANDROID_LOGCAT_TEXT_EVENTS"\n"
2622         "\t"INTERFACE_ANDROID_LOGCAT_TEXT_CRASH"\n"
2623         "\t"INTERFACE_ANDROID_BLUETOOTH_HCIDUMP"\n"
2624         "\t"INTERFACE_ANDROID_BLUETOOTH_EXTERNAL_PARSER"\n"
2625         "\t"INTERFACE_ANDROID_BLUETOOTH_BTSNOOP_NET"\n"
2626         "\t"INTERFACE_ANDROID_TCPDUMP"\n"
2627         "\n"
2628         "\t""DEVICEID is the identifier of the device provided by Android SDK (see \"adb devices\")\n"
2629         "\t""For example: W3D7N15C29005648""\n",
2630
2631         argv[0], argv[0], argv[0], argv[0]);
2632     extcap_help_add_header(extcap_conf, help_header);
2633     g_free(help_header);
2634
2635     extcap_help_add_option(extcap_conf, "--help", "print this help");
2636     extcap_help_add_option(extcap_conf, "--adb-server-ip <IP>", "the IP address of the ADB server");
2637     extcap_help_add_option(extcap_conf, "--adb-server-tcp-port <port>", "the TCP port of the ADB server");
2638     extcap_help_add_option(extcap_conf, "--logcat-text", "use logcat text format");
2639     extcap_help_add_option(extcap_conf, "--logcat-ignore-log-buffer", "ignore log buffer");
2640     extcap_help_add_option(extcap_conf, "--logcat-custom-options <text>", "use custom logcat parameters");
2641     extcap_help_add_option(extcap_conf, "--bt-server-tcp-port <port>", "bluetooth server TCP port");
2642     extcap_help_add_option(extcap_conf, "--bt-forward-socket <path>", "bluetooth forward socket");
2643     extcap_help_add_option(extcap_conf, "--bt-local-ip <IP>", "the bluetooth local IP");
2644     extcap_help_add_option(extcap_conf, "--bt-local-tcp-port <port>", "the bluetooth local TCP port");
2645
2646     opterr = 0;
2647     optind = 0;
2648
2649     if (argc == 1) {
2650         extcap_help_print(extcap_conf);
2651         ret = EXIT_CODE_SUCCESS;
2652         goto end;
2653     }
2654
2655     while ((result = getopt_long(argc, argv, "", longopts, &option_idx)) != -1) {
2656         switch (result) {
2657
2658         case OPT_VERSION:
2659             printf("%s\n", extcap_conf->version);
2660             ret = EXIT_CODE_SUCCESS;
2661             goto end;
2662         case OPT_HELP:
2663             extcap_help_print(extcap_conf);
2664             ret = EXIT_CODE_SUCCESS;
2665             goto end;
2666         case OPT_CONFIG_ADB_SERVER_IP:
2667             adb_server_ip = optarg;
2668             break;
2669         case OPT_CONFIG_ADB_SERVER_TCP_PORT:
2670             adb_server_tcp_port = &local_adb_server_tcp_port;
2671             if (!optarg){
2672                 g_warning("Impossible exception. Parameter required argument, but there is no it right now.");
2673                 goto end;
2674             }
2675             if (!ws_strtou16(optarg, NULL, adb_server_tcp_port)) {
2676                 g_warning("Invalid adb server TCP port: %s", optarg);
2677                 goto end;
2678             }
2679             break;
2680         case OPT_CONFIG_LOGCAT_TEXT:
2681             if (optarg && !*optarg)
2682                 logcat_text = TRUE;
2683             else
2684                 logcat_text = (g_ascii_strncasecmp(optarg, "TRUE", 4) == 0);
2685             break;
2686         case OPT_CONFIG_LOGCAT_IGNORE_LOG_BUFFER:
2687             if (optarg == NULL || (optarg && !*optarg))
2688                 logcat_ignore_log_buffer = TRUE;
2689             else
2690                 logcat_ignore_log_buffer = (g_ascii_strncasecmp(optarg, "TRUE", 4) == 0);
2691             break;
2692         case OPT_CONFIG_LOGCAT_CUSTOM_OPTIONS:
2693             if (optarg == NULL || (optarg && *optarg == '\0')) {
2694                 logcat_custom_parameter = NULL;
2695                 break;
2696             }
2697
2698             if (g_regex_match_simple("(^|\\s)-[bBcDfgLnpPrv]", optarg, (GRegexCompileFlags)0, (GRegexMatchFlags)0)) {
2699                 g_error("Found prohibited option in logcat-custom-options");
2700                 return EXIT_CODE_GENERIC;
2701             }
2702
2703             logcat_custom_parameter = optarg;
2704
2705             break;
2706         case OPT_CONFIG_BT_SERVER_TCP_PORT:
2707             bt_server_tcp_port = &local_bt_server_tcp_port;
2708             if (!optarg){
2709                 g_warning("Impossible exception. Parameter required argument, but there is no it right now.");
2710                 goto end;
2711             }
2712             if (!ws_strtou16(optarg, NULL, bt_server_tcp_port)) {
2713                 g_warning("Invalid bluetooth server TCP port: %s", optarg);
2714                 goto end;
2715             }
2716             break;
2717         case OPT_CONFIG_BT_FORWARD_SOCKET:
2718             bt_forward_socket = (g_ascii_strncasecmp(optarg, "TRUE", 4) == 0);
2719             break;
2720         case OPT_CONFIG_BT_LOCAL_IP:
2721             bt_local_ip = optarg;
2722             break;
2723         case OPT_CONFIG_BT_LOCAL_TCP_PORT:
2724             bt_local_tcp_port = &local_bt_local_tcp_port;
2725             if (!optarg){
2726                 g_warning("Impossible exception. Parameter required argument, but there is no it right now.");
2727                 goto end;
2728             }
2729             if (!ws_strtou16(optarg, NULL, bt_local_tcp_port)) {
2730                 g_warning("Invalid bluetooth local tcp port: %s", optarg);
2731                 goto end;
2732             }
2733             break;
2734         default:
2735             if (!extcap_base_parse_options(extcap_conf, result - EXTCAP_OPT_LIST_INTERFACES, optarg))
2736             {
2737                 g_warning("Invalid argument <%s>. Try --help.\n", argv[optind - 1]);
2738                 goto end;
2739             }
2740         }
2741     }
2742
2743     if (!adb_server_ip)
2744         adb_server_ip = default_adb_server_ip;
2745
2746     if (!adb_server_tcp_port)
2747         adb_server_tcp_port = &default_adb_server_tcp_port;
2748
2749     if (!bt_server_tcp_port)
2750         bt_server_tcp_port = &default_bt_server_tcp_port;
2751
2752     if (!bt_local_ip)
2753         bt_local_ip = default_bt_local_ip;
2754
2755     if (!bt_local_tcp_port)
2756         bt_local_tcp_port = &default_bt_local_tcp_port;
2757
2758 #ifdef _WIN32
2759     result = WSAStartup(MAKEWORD(1,1), &wsaData);
2760     if (result != 0) {
2761         g_warning("WSAStartup failed with %d", result);
2762         goto end;
2763     }
2764 #endif  /* _WIN32 */
2765
2766     extcap_cmdline_debug(argv, argc);
2767
2768     if (extcap_conf->do_list_interfaces)
2769         register_interfaces(extcap_conf, adb_server_ip, adb_server_tcp_port);
2770
2771     /* NOTE:
2772      * extcap implementation calls androiddump --extcap-dlts for each interface.
2773      * The only way to know whether an interface exists or not is to go through the
2774      * whole process of listing all interfaces (i.e. calling register_interfaces
2775      * function). Since being a system resource heavy operation and repeated for
2776      * each interface instead register a fake interface to be returned for dlt
2777      * listing only purpose
2778      */
2779     if (extcap_conf->do_list_dlts) {
2780         new_fake_interface_for_list_dlts(extcap_conf, extcap_conf->interface);
2781     }
2782
2783     if (extcap_base_handle_interface(extcap_conf)) {
2784         ret = EXIT_CODE_SUCCESS;
2785         goto end;
2786     }
2787
2788     if (extcap_conf->show_config) {
2789         ret = list_config(extcap_conf->interface);
2790         goto end;
2791     }
2792
2793     if (extcap_conf->capture) {
2794         if (extcap_conf->interface && is_logcat_interface(extcap_conf->interface))
2795             if (logcat_text)
2796                 ret = capture_android_logcat_text(extcap_conf->interface,
2797                         extcap_conf->fifo, adb_server_ip, adb_server_tcp_port,
2798                         logcat_ignore_log_buffer, logcat_custom_parameter);
2799             else
2800                 ret = capture_android_logcat(extcap_conf->interface,
2801                         extcap_conf->fifo, adb_server_ip, adb_server_tcp_port);
2802         else if (extcap_conf->interface && is_logcat_text_interface(extcap_conf->interface))
2803             ret = capture_android_logcat_text(extcap_conf->interface,
2804                     extcap_conf->fifo, adb_server_ip, adb_server_tcp_port,
2805                     logcat_ignore_log_buffer, logcat_custom_parameter);
2806         else if (extcap_conf->interface && is_specified_interface(extcap_conf->interface, INTERFACE_ANDROID_BLUETOOTH_HCIDUMP))
2807             ret = capture_android_bluetooth_hcidump(extcap_conf->interface, extcap_conf->fifo, adb_server_ip, adb_server_tcp_port);
2808         else if (extcap_conf->interface && is_specified_interface(extcap_conf->interface, INTERFACE_ANDROID_BLUETOOTH_EXTERNAL_PARSER))
2809             ret = capture_android_bluetooth_external_parser(extcap_conf->interface, extcap_conf->fifo, adb_server_ip, adb_server_tcp_port,
2810                     bt_server_tcp_port, bt_forward_socket, bt_local_ip, bt_local_tcp_port);
2811         else if (extcap_conf->interface && (is_specified_interface(extcap_conf->interface, INTERFACE_ANDROID_BLUETOOTH_BTSNOOP_NET)))
2812             ret = capture_android_bluetooth_btsnoop_net(extcap_conf->interface, extcap_conf->fifo, adb_server_ip, adb_server_tcp_port);
2813         else if (extcap_conf->interface && (is_specified_interface(extcap_conf->interface,INTERFACE_ANDROID_TCPDUMP)))
2814             ret = capture_android_tcpdump(extcap_conf->interface, extcap_conf->fifo, adb_server_ip, adb_server_tcp_port);
2815
2816         goto end;
2817     }
2818
2819     /* no action was given, assume success */
2820     ret = EXIT_CODE_SUCCESS;
2821
2822 end:
2823     /* clean up stuff */
2824     extcap_base_cleanup(&extcap_conf);
2825 #ifndef ANDROIDDUMP_USE_LIBPCAP
2826     wtap_cleanup();
2827 #endif
2828
2829     return ret;
2830 }
2831
2832 #ifdef _WIN32
2833 int _stdcall
2834 WinMain (struct HINSTANCE__ *hInstance,
2835          struct HINSTANCE__ *hPrevInstance,
2836          char               *lpszCmdLine,
2837          int                 nCmdShow)
2838 {
2839     return main(__argc, __argv);
2840 }
2841 #endif
2842
2843 /*
2844  * Editor modelines  -  http://www.wireshark.org/tools/modelines.html
2845  *
2846  * Local variables:
2847  * c-basic-offset: 4
2848  * tab-width: 8
2849  * indent-tabs-mode: nil
2850  * End:
2851  *
2852  * vi: set shiftwidth=4 tabstop=8 expandtab:
2853  * :indentSize=4:tabSize=8:noTabs=true:
2854  */