From c2db2b6accc7888df514261a7240e7759df95a4c Mon Sep 17 00:00:00 2001 From: The Android Open Source Project Date: Fri, 9 Jan 2009 17:51:21 -0800 Subject: auto import from //branches/cupcake/...@125939 --- tcpdump.c | 147 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 147 insertions(+) create mode 100644 tcpdump.c (limited to 'tcpdump.c') 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 +#include +#include + +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; +} + -- cgit v1.1