18b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Copyright (C) 2008 The Android Open Source Project
28b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project**
38b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project** This software is licensed under the terms of the GNU General Public
48b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project** License version 2, as published by the Free Software Foundation, and
58b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project** may be copied, distributed, and modified under those terms.
68b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project**
78b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project** This program is distributed in the hope that it will be useful,
88b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project** but WITHOUT ANY WARRANTY; without even the implied warranty of
98b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project** GNU General Public License for more details.
118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project*/
126e2eb78f2b52b6fff73a72995bc4356d6e67e773David 'Digit' Turner#include "android/tcpdump.h"
138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include <stdio.h>
148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include <stdlib.h>
158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include <sys/time.h>
168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint  qemu_tcpdump_active;
188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic FILE*     capture_file;
208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic uint64_t  capture_count;
218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic uint64_t  capture_size;
228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int       capture_init;
238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void
258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectcapture_atexit(void)
268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (qemu_tcpdump_active) {
288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        fclose(capture_file);
298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        qemu_tcpdump_active = 0;
308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* See http://wiki.wireshark.org/Development/LibpcapFileFormat for
348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * the complete description of the packet capture file format
358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */
368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define  PCAP_MAGIC     0xa1b2c3d4
388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define  PCAP_MAJOR     2
398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define  PCAP_MINOR     4
408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define  PCAP_SNAPLEN   65535
418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define  PCAP_ETHERNET  1
428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectpcap_write_header( FILE*  out )
458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    typedef struct {
478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        uint32_t   magic;
488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        uint16_t   version_major;
498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        uint16_t   version_minor;
508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        int32_t    this_zone;
518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        uint32_t   sigfigs;
528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        uint32_t   snaplen;
538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        uint32_t   network;
548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } PcapHeader;
558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    PcapHeader  h;
578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    h.magic         = PCAP_MAGIC;
598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    h.version_major = PCAP_MAJOR;
608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    h.version_minor = PCAP_MINOR;
618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    h.this_zone     = 0;
628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    h.sigfigs       = 0;  /* all tools set it to 0 in practice */
638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    h.snaplen       = PCAP_SNAPLEN;
648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    h.network       = PCAP_ETHERNET;
658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (fwrite(&h, sizeof(h), 1, out) != 1) {
678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint
738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectqemu_tcpdump_start( const char*  filepath )
748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!capture_init) {
768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        capture_init = 1;
778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        atexit(capture_atexit);
788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    qemu_tcpdump_stop();
818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (filepath == NULL)
838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    capture_file = fopen(filepath, "wb");
868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (capture_file == NULL)
878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (pcap_write_header(capture_file) < 0)
908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    qemu_tcpdump_active = 1;
938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid
978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectqemu_tcpdump_stop( void )
988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!qemu_tcpdump_active)
1008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return;
1018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    qemu_tcpdump_active = 0;
1038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    capture_count = 0;
1058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    capture_size  = 0;
1068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    fclose(capture_file);
1088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    capture_file = NULL;
1098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
1108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid
1128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectqemu_tcpdump_packet( const void*  base, int  len )
1138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    typedef struct {
1158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        uint32_t  ts_sec;
1168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        uint32_t  ts_usec;
1178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        uint32_t  incl_len;
1188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        uint32_t  orig_len;
1198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } PacketHeader;
1208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    PacketHeader    h;
1228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    struct timeval  now;
1238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int             len2 = len;
1248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (len2 > PCAP_SNAPLEN)
1268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        len2 = PCAP_SNAPLEN;
1278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    gettimeofday(&now, NULL);
1298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    h.ts_sec   = (uint32_t) now.tv_sec;
1308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    h.ts_usec  = (uint32_t) now.tv_usec;
1318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    h.incl_len = (uint32_t) len2;
1328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    h.orig_len = (uint32_t) len;
1338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    fwrite( &h, sizeof(h), 1, capture_file );
1358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    fwrite( base, 1, len2, capture_file );
1368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    capture_count += 1;
1388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    capture_size  += len2;
1398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
1408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid
1428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectqemu_tcpdump_stats( uint64_t  *pcount, uint64_t*  psize )
1438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    *pcount = capture_count;
1458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    *psize  = capture_size;
1468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
1478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
148