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 -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);

Reply via email to