This patch allows to capture the traffic flowing through a particular vlan in a
tcpdump compatible pcap file.
The patch is identical to the one created some time back, however it was
updated to apply to HEAD.
Usage: -net nic,pcap=capture_file.pcap
__
Sent from Yahoo! - the World's favourite mail http://uk.mail.yahoo.com
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 - 1.376
+++ vl.c 5 Dec 2007 13:38:04 -
@@ -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 < 100)
+ ++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 stringset 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 - 1.1
+++ net.h 5 Dec 2007 13:38:04 -
@@ -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 0x
+
/* 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);