Move tcpdump.h -> include/android/tcpdump.h

+ tcpdump.c -> android/qemu-tcpdump.c

Change-Id: Ib3a19f62f910b6562285fab3bcc98178ea9a4e9e
diff --git a/android/console.c b/android/console.c
index 22fdc17..a66b788 100644
--- a/android/console.c
+++ b/android/console.c
@@ -36,7 +36,7 @@
 #include "android/utils/debug.h"
 #include "android/utils/stralloc.h"
 #include "android/config/config.h"
-#include "tcpdump.h"
+#include "android/tcpdump.h"
 #include "net/net.h"
 #include "monitor/monitor.h"
 
diff --git a/android/qemu-tcpdump.c b/android/qemu-tcpdump.c
new file mode 100644
index 0000000..585a5a0
--- /dev/null
+++ b/android/qemu-tcpdump.c
@@ -0,0 +1,147 @@
+/* Copyright (C) 2008 The Android Open Source Project
+**
+** This software is licensed under the terms of the GNU General Public
+** License version 2, as published by the Free Software Foundation, and
+** may be copied, distributed, and modified under those terms.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+** GNU General Public License for more details.
+*/
+#include "android/tcpdump.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/time.h>
+
+int  qemu_tcpdump_active;
+
+static FILE*     capture_file;
+static uint64_t  capture_count;
+static uint64_t  capture_size;
+static int       capture_init;
+
+static void
+capture_atexit(void)
+{
+    if (qemu_tcpdump_active) {
+        fclose(capture_file);
+        qemu_tcpdump_active = 0;
+    }
+}
+
+/* See http://wiki.wireshark.org/Development/LibpcapFileFormat for
+ * the complete description of the packet capture file format
+ */
+
+#define  PCAP_MAGIC     0xa1b2c3d4
+#define  PCAP_MAJOR     2
+#define  PCAP_MINOR     4
+#define  PCAP_SNAPLEN   65535
+#define  PCAP_ETHERNET  1
+
+static int
+pcap_write_header( FILE*  out )
+{
+    typedef struct {
+        uint32_t   magic;
+        uint16_t   version_major;
+        uint16_t   version_minor;
+        int32_t    this_zone;
+        uint32_t   sigfigs;
+        uint32_t   snaplen;
+        uint32_t   network;
+    } PcapHeader;
+
+    PcapHeader  h;
+
+    h.magic         = PCAP_MAGIC;
+    h.version_major = PCAP_MAJOR;
+    h.version_minor = PCAP_MINOR;
+    h.this_zone     = 0;
+    h.sigfigs       = 0;  /* all tools set it to 0 in practice */
+    h.snaplen       = PCAP_SNAPLEN;
+    h.network       = PCAP_ETHERNET;
+
+    if (fwrite(&h, sizeof(h), 1, out) != 1) {
+        return -1;
+    }
+    return 0;
+}
+
+int
+qemu_tcpdump_start( const char*  filepath )
+{
+    if (!capture_init) {
+        capture_init = 1;
+        atexit(capture_atexit);
+    }
+
+    qemu_tcpdump_stop();
+
+    if (filepath == NULL)
+        return -1;
+
+    capture_file = fopen(filepath, "wb");
+    if (capture_file == NULL)
+        return -1;
+
+    if (pcap_write_header(capture_file) < 0)
+        return -1;
+
+    qemu_tcpdump_active = 1;
+    return 0;
+}
+
+void
+qemu_tcpdump_stop( void )
+{
+    if (!qemu_tcpdump_active)
+        return;
+
+    qemu_tcpdump_active = 0;
+
+    capture_count = 0;
+    capture_size  = 0;
+
+    fclose(capture_file);
+    capture_file = NULL;
+}
+
+void
+qemu_tcpdump_packet( const void*  base, int  len )
+{
+    typedef struct {
+        uint32_t  ts_sec;
+        uint32_t  ts_usec;
+        uint32_t  incl_len;
+        uint32_t  orig_len;
+    } PacketHeader;
+
+    PacketHeader    h;
+    struct timeval  now;
+    int             len2 = len;
+
+    if (len2 > PCAP_SNAPLEN)
+        len2 = PCAP_SNAPLEN;
+
+    gettimeofday(&now, NULL);
+    h.ts_sec   = (uint32_t) now.tv_sec;
+    h.ts_usec  = (uint32_t) now.tv_usec;
+    h.incl_len = (uint32_t) len2;
+    h.orig_len = (uint32_t) len;
+
+    fwrite( &h, sizeof(h), 1, capture_file );
+    fwrite( base, 1, len2, capture_file );
+
+    capture_count += 1;
+    capture_size  += len2;
+}
+
+void
+qemu_tcpdump_stats( uint64_t  *pcount, uint64_t*  psize )
+{
+    *pcount = capture_count;
+    *psize  = capture_size;
+}
+