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