aboutsummaryrefslogtreecommitdiffstats
path: root/tcpdump.c
diff options
context:
space:
mode:
authorThe Android Open Source Project <initial-contribution@android.com>2009-03-03 19:30:32 -0800
committerThe Android Open Source Project <initial-contribution@android.com>2009-03-03 19:30:32 -0800
commit8b23a6c7e1aee255004dd19098d4c2462b61b849 (patch)
tree7a4d682ba51f0ff0364c5ca2509f515bdaf96de9 /tcpdump.c
parentf721e3ac031f892af46f255a47d7f54a91317b30 (diff)
downloadexternal_qemu-8b23a6c7e1aee255004dd19098d4c2462b61b849.zip
external_qemu-8b23a6c7e1aee255004dd19098d4c2462b61b849.tar.gz
external_qemu-8b23a6c7e1aee255004dd19098d4c2462b61b849.tar.bz2
auto import from //depot/cupcake/@135843
Diffstat (limited to 'tcpdump.c')
-rw-r--r--tcpdump.c147
1 files changed, 147 insertions, 0 deletions
diff --git a/tcpdump.c b/tcpdump.c
new file mode 100644
index 0000000..e562253
--- /dev/null
+++ b/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 "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;
+}
+