Index: vl.c =================================================================== RCS file: /sources/qemu/qemu/vl.c,v retrieving revision 1.376 diff -u -r1.376 vl.c --- vl.c 4 Dec 2007 00:10:34 -0000 1.376 +++ vl.c 5 Dec 2007 13:38:04 -0000 @@ -3588,6 +3588,8 @@ return NULL; vlan->id = id; vlan->next = NULL; + vlan->pcap_fh = -1; + vlan->last_packet_time = 0; pvlan = &first_vlan; while (*pvlan != NULL) pvlan = &(*pvlan)->next; @@ -3635,6 +3637,22 @@ { VLANState *vlan = vc1->vlan; VLANClientState *vc; + + if (vlan->pcap_fh >= 0) { + vlan->packet_header.timestamp_sec = time(NULL); + if (vlan->packet_header.timestamp_sec == vlan->last_packet_time) { + if (vlan->packet_header.timestamp_usec < 1000000) + ++vlan->packet_header.timestamp_usec; + } else { + vlan->packet_header.timestamp_usec = 0; + vlan->last_packet_time = vlan->packet_header.timestamp_sec; + } + + vlan->packet_header.orig_len = size; + vlan->packet_header.saved_len = (size > MAX_CAPTURED_PACKET_SIZE) ? MAX_CAPTURED_PACKET_SIZE : size; + write(vlan->pcap_fh, &vlan->packet_header, sizeof(PCAPPacketHeader)); + write(vlan->pcap_fh, buf, vlan->packet_header.saved_len); + } #if 0 printf("vlan %d send:\n", vlan->id); @@ -4642,6 +4660,7 @@ char buf[1024]; int vlan_id, ret; VLANState *vlan; + PCAPHeader initial_header; p = str; q = device; @@ -4662,6 +4681,22 @@ fprintf(stderr, "Could not create vlan %d\n", vlan_id); return -1; } + if (get_param_value(buf, sizeof(buf), "pcap", p)) { + vlan->pcap_fh = open(buf, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0644); + if (vlan->pcap_fh < 0) { + fprintf(stderr, "Failed to open capture file \"%s\": %d\n", buf, errno); + return -1; + } + + initial_header.magic_number = 0xa1b2c3d4; + initial_header.version_major = 2; + initial_header.version_minor = 4; + initial_header.thiszone = 0; + initial_header.sigfigs = 0; + initial_header.snaplen = MAX_CAPTURED_PACKET_SIZE; + initial_header.network = 1; /* Ethernet */ + write(vlan->pcap_fh, &initial_header, sizeof(initial_header)); + } if (!strcmp(device, "nic")) { NICInfo *nd; uint8_t *macaddr; @@ -7481,8 +7516,10 @@ "-name string set the name of the guest\n" "\n" "Network options:\n" - "-net nic[,vlan=n][,macaddr=addr][,model=type]\n" + "-net nic[,vlan=n][,macaddr=addr][,model=type][,pcap=filename]\n" " create a new Network Interface Card and connect it to VLAN 'n'\n" + " optionally save the traffic which flows through VLAN 'n' to\n" + " 'filename' in pcap (tcpdump) format\n" #ifdef CONFIG_SLIRP "-net user[,vlan=n][,hostname=host]\n" " connect the user mode network stack to VLAN 'n' and send\n" @@ -8931,5 +8968,11 @@ } } #endif + + /* close capture files associated with any vlan */ + for(vlan = first_vlan; vlan != NULL; vlan = vlan->next) + if (vlan->pcap_fh >= 0) + close(vlan->pcap_fh); + return 0; } Index: net.h =================================================================== RCS file: /sources/qemu/qemu/net.h,v retrieving revision 1.1 diff -u -r1.1 net.h --- net.h 17 Nov 2007 17:14:38 -0000 1.1 +++ net.h 5 Dec 2007 13:38:04 -0000 @@ -1,6 +1,27 @@ #ifndef QEMU_NET_H #define QEMU_NET_H +/* PCAP support */ +/* source: http://wiki.wireshark.org/Development/LibpcapFileFormat */ +typedef struct { + uint32_t magic_number; + uint16_t version_major; + uint16_t version_minor; + int32_t thiszone; + uint32_t sigfigs; + uint32_t snaplen; + uint32_t network; +} PCAPHeader; + +typedef struct { + uint32_t timestamp_sec; + uint32_t timestamp_usec; + uint32_t saved_len; + uint32_t orig_len; +} PCAPPacketHeader; + +#define MAX_CAPTURED_PACKET_SIZE 0xFFFF + /* VLANs support */ typedef struct VLANClientState VLANClientState; @@ -21,6 +42,10 @@ VLANClientState *first_client; struct VLANState *next; unsigned int nb_guest_devs, nb_host_devs; + /* Filehandle for the capture file */ + int pcap_fh; + time_t last_packet_time; + PCAPPacketHeader packet_header; }; VLANState *qemu_find_vlan(int id);