• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* 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 
17 int  qemu_tcpdump_active;
18 
19 static FILE*     capture_file;
20 static uint64_t  capture_count;
21 static uint64_t  capture_size;
22 static int       capture_init;
23 
24 static void
capture_atexit(void)25 capture_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 
43 static int
pcap_write_header(FILE * out)44 pcap_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 
72 int
qemu_tcpdump_start(const char * filepath)73 qemu_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 
96 void
qemu_tcpdump_stop(void)97 qemu_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 
111 void
qemu_tcpdump_packet(const void * base,int len)112 qemu_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 
141 void
qemu_tcpdump_stats(uint64_t * pcount,uint64_t * psize)142 qemu_tcpdump_stats( uint64_t  *pcount, uint64_t*  psize )
143 {
144     *pcount = capture_count;
145     *psize  = capture_size;
146 }
147 
148