Hello all.
Attached you find an updated version of my patch to dump the traffic on a given
interface to a tcpdump file. The changes are:
-moved from f* functions (fopen, fwrite) to the more basic functions (open,
write, etc) because this seems to be the norm in the source code
-fixed some formatting mistakes
-modified the help (which is printed out when qemu is excuted with no
parameters) to display the new option
-made the code more portable (by using the types uint32_t, etc)
-added the code to properly close the files when qemu is shut down
Before anyone asks :), no endianess conversion needs to be applied to the
things written to the file, because it is specified that the reader shall
detect the endianess of the file based on the signature in the header.
Best wishes
___________________________________________________________
All New Yahoo! Mail – Tired of unwanted email come-ons? Let our SpamGuard
protect you. http://uk.docs.yahoo.com/nowyoucan.html
Index: vl.c
===================================================================
RCS file: /sources/qemu/qemu/vl.c,v
retrieving revision 1.317
diff -u -r1.317 vl.c
--- vl.c 29 Jun 2007 23:26:08 -0000 1.317
+++ vl.c 1 Jul 2007 08:44:43 -0000
@@ -3163,9 +3163,28 @@
while (*pvlan != NULL)
pvlan = &(*pvlan)->next;
*pvlan = vlan;
+
+ //initialize the packet capture options
+ vlan->pcap_file = 0;
+ vlan->last_written_time = 0;
+
return vlan;
}
+/* close packet capture files if it's the case */
+void pcap_close_files()
+{
+ int i;
+ for (i = 0; i <= nb_nics; i++)
+ {
+ if (nd_table[i].vlan->pcap_file)
+ {
+ close(nd_table[i].vlan->pcap_file);
+ nd_table[i].vlan->pcap_file = 0;
+ }
+ }
+}
+
VLANClientState *qemu_new_vlan_client(VLANState *vlan,
IOReadHandler *fd_read,
IOCanRWHandler *fd_can_read,
@@ -3206,6 +3225,22 @@
{
VLANState *vlan = vc1->vlan;
VLANClientState *vc;
+ PCAPRecordHeader pcap_record_header;
+
+ if (vlan->pcap_file) {
+ pcap_record_header.ts_sec = time(NULL);
+ if (pcap_record_header.ts_sec == vlan->last_written_time) {
+ pcap_record_header.ts_usec = vlan->last_written_time;
+ if (vlan->last_written_time < 9999) vlan->last_written_time++;
+ } else {
+ pcap_record_header.ts_usec = 0;
+ vlan->last_written_time = 0;
+ }
+ pcap_record_header.orig_len = size;
+ pcap_record_header.incl_len = (size > 0xFFFF) ? 0xFFFF : size;
+ write(vlan->pcap_file, &pcap_record_header, sizeof(pcap_record_header));
+ write(vlan->pcap_file, buf, pcap_record_header.incl_len);
+ }
#if 0
printf("vlan %d send:\n", vlan->id);
@@ -4200,6 +4235,24 @@
if (get_param_value(buf, sizeof(buf), "model", p)) {
nd->model = strdup(buf);
}
+ if (get_param_value(buf, sizeof(buf), "pcap", p)) {
+ vlan->pcap_file = open(buf, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0644);
+ if (!vlan->pcap_file) {
+ fprintf(stderr, "failed to open pcap file: %d\n", errno);
+ return -1;
+ }
+ /* write out the standard tcpdump file header
+ reference: http://wiki.wireshark.org/Development/LibpcapFileFormat */
+ PCAPHeader hdr;
+ hdr.magic_number = 0xa1b2c3d4;
+ hdr.version_major = 2;
+ hdr.version_minor = 4;
+ hdr.thiszone = 0;
+ hdr.sigfigs = 0;
+ hdr.snaplen = 0xFFFF;
+ hdr.network = 1;
+ write(vlan->pcap_file, &hdr, sizeof(hdr));
+ }
nd->vlan = vlan;
nb_nics++;
vlan->nb_guest_devs++;
@@ -6624,7 +6677,7 @@
"-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"
#ifdef CONFIG_SLIRP
"-net user[,vlan=n][,hostname=host]\n"
@@ -8050,5 +8103,8 @@
main_loop();
quit_timers();
+
+ pcap_close_files();
+
return 0;
}
Index: vl.h
===================================================================
RCS file: /sources/qemu/qemu/vl.h,v
retrieving revision 1.255
diff -u -r1.255 vl.h
--- vl.h 30 Jun 2007 17:32:17 -0000 1.255
+++ vl.h 1 Jul 2007 08:44:44 -0000
@@ -391,6 +391,11 @@
VLANClientState *first_client;
struct VLANState *next;
unsigned int nb_guest_devs, nb_host_devs;
+
+ /* used to perform packed capture
+ and to set the time stamps on the captured packets */
+ int pcap_file;
+ time_t last_written_time;
} VLANState;
VLANState *qemu_find_vlan(int id);
@@ -404,6 +409,24 @@
void do_info_network(void);
+/* PCAP file structures */
+typedef struct PCAPHeader {
+ uint32_t magic_number; /* magic number */
+ uint16_t version_major; /* major version number */
+ uint16_t version_minor; /* minor version number */
+ int32_t thiszone; /* GMT to local correction */
+ uint32_t sigfigs; /* accuracy of timestamps */
+ uint32_t snaplen; /* max length of captured packets, in octets */
+ uint32_t network; /* data link type */
+} PCAPHeader;
+
+typedef struct PCAPRecordHeader {
+ uint32_t ts_sec; /* timestamp seconds */
+ uint32_t ts_usec; /* timestamp microseconds */
+ uint32_t incl_len; /* number of octets of packet saved in file */
+ uint32_t orig_len; /* actual length of packet */
+} PCAPRecordHeader;
+
/* TAP win32 */
int tap_win32_init(VLANState *vlan, const char *ifname);