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