blob: e562253e639bc2a5a6ce10b13181d96337af4f58 [file] [log] [blame]
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001/* Copyright (C) 2008 The Android Open Source Project
2**
3** This software is licensed under the terms of the GNU General Public
4** License version 2, as published by the Free Software Foundation, and
5** may be copied, distributed, and modified under those terms.
6**
7** This program is distributed in the hope that it will be useful,
8** but WITHOUT ANY WARRANTY; without even the implied warranty of
9** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10** GNU General Public License for more details.
11*/
12#include "tcpdump.h"
13#include <stdio.h>
14#include <stdlib.h>
15#include <sys/time.h>
16
17int qemu_tcpdump_active;
18
19static FILE* capture_file;
20static uint64_t capture_count;
21static uint64_t capture_size;
22static int capture_init;
23
24static void
25capture_atexit(void)
26{
27 if (qemu_tcpdump_active) {
28 fclose(capture_file);
29 qemu_tcpdump_active = 0;
30 }
31}
32
33/* See http://wiki.wireshark.org/Development/LibpcapFileFormat for
34 * the complete description of the packet capture file format
35 */
36
37#define PCAP_MAGIC 0xa1b2c3d4
38#define PCAP_MAJOR 2
39#define PCAP_MINOR 4
40#define PCAP_SNAPLEN 65535
41#define PCAP_ETHERNET 1
42
43static int
44pcap_write_header( FILE* out )
45{
46 typedef struct {
47 uint32_t magic;
48 uint16_t version_major;
49 uint16_t version_minor;
50 int32_t this_zone;
51 uint32_t sigfigs;
52 uint32_t snaplen;
53 uint32_t network;
54 } PcapHeader;
55
56 PcapHeader h;
57
58 h.magic = PCAP_MAGIC;
59 h.version_major = PCAP_MAJOR;
60 h.version_minor = PCAP_MINOR;
61 h.this_zone = 0;
62 h.sigfigs = 0; /* all tools set it to 0 in practice */
63 h.snaplen = PCAP_SNAPLEN;
64 h.network = PCAP_ETHERNET;
65
66 if (fwrite(&h, sizeof(h), 1, out) != 1) {
67 return -1;
68 }
69 return 0;
70}
71
72int
73qemu_tcpdump_start( const char* filepath )
74{
75 if (!capture_init) {
76 capture_init = 1;
77 atexit(capture_atexit);
78 }
79
80 qemu_tcpdump_stop();
81
82 if (filepath == NULL)
83 return -1;
84
85 capture_file = fopen(filepath, "wb");
86 if (capture_file == NULL)
87 return -1;
88
89 if (pcap_write_header(capture_file) < 0)
90 return -1;
91
92 qemu_tcpdump_active = 1;
93 return 0;
94}
95
96void
97qemu_tcpdump_stop( void )
98{
99 if (!qemu_tcpdump_active)
100 return;
101
102 qemu_tcpdump_active = 0;
103
104 capture_count = 0;
105 capture_size = 0;
106
107 fclose(capture_file);
108 capture_file = NULL;
109}
110
111void
112qemu_tcpdump_packet( const void* base, int len )
113{
114 typedef struct {
115 uint32_t ts_sec;
116 uint32_t ts_usec;
117 uint32_t incl_len;
118 uint32_t orig_len;
119 } PacketHeader;
120
121 PacketHeader h;
122 struct timeval now;
123 int len2 = len;
124
125 if (len2 > PCAP_SNAPLEN)
126 len2 = PCAP_SNAPLEN;
127
128 gettimeofday(&now, NULL);
129 h.ts_sec = (uint32_t) now.tv_sec;
130 h.ts_usec = (uint32_t) now.tv_usec;
131 h.incl_len = (uint32_t) len2;
132 h.orig_len = (uint32_t) len;
133
134 fwrite( &h, sizeof(h), 1, capture_file );
135 fwrite( base, 1, len2, capture_file );
136
137 capture_count += 1;
138 capture_size += len2;
139}
140
141void
142qemu_tcpdump_stats( uint64_t *pcount, uint64_t* psize )
143{
144 *pcount = capture_count;
145 *psize = capture_size;
146}
147