Home | History | Annotate | Download | only in qemu
      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
     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
     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
     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
     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
    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
    142 qemu_tcpdump_stats( uint64_t  *pcount, uint64_t*  psize )
    143 {
    144     *pcount = capture_count;
    145     *psize  = capture_size;
    146 }
    147 
    148