Re: [Qemu-devel] bug in qemu last win32 snapshot (12132007)
I didn't see any messages indicating that my patch was committed to CVS. Maybe I missed it. I someone could confirm that this is indeed the case, I can look at it Monday on a Windows system... - Original Message From: Sergey Bychkov <[EMAIL PROTECTED]> To: qemu-devel@nongnu.org Sent: Thursday, 3 January, 2008 9:42:18 PM Subject: Re: [Qemu-devel] bug in qemu last win32 snapshot (12132007) - Original Message - From: "Sebastien WILLEMIJNS" <[EMAIL PROTECTED]> To: Sent: 2.01.2008 11:00 Subject: Re: [Qemu-devel] bug in qemu last win32 snapshot (12132007) >... but it is a new information to write inside win documentation >because if i use qemu-0.9.0 windows stable build >"\\" is not mandatory... Looks like result of patch posted by "Cd-MaN" 30.12.2007 12:01 EEST Sergey Bychkow ICQ: 21014758 FTN: 2:450/118.55 __ Sent from Yahoo! Mail - a smarter inbox http://uk.mail.yahoo.com
[Qemu-devel] [PATCH] Make relative path correct in bdrv_create
Description: When using base images (ie difference disks), the path of the backing image is interpreted correctly as being relative to the path of the difference image (which is very nice). However, at creation time, the path is copied verbatim from the command line, which can lead to incorrect results if the "qemu-img create" is issued from a different location than the final location of the difference image. For example: if we have /home/cdman/qemu/winxp.img and we want to create /home/cdman/Desktop/diff.img and we are currently in the /home/cdman directory, we would say: qemu-img create -f qcow2 -b qemu/winxp.img Desktop/diff.img With the current source, this would write "qemu/winxp.img" in the diff.img file, however the correct thing to write would be "../qemu/winxp.img" (because the path should be relative to the location of diff.img). The attached patch fixes this. Warning! It contains string manipulation in C (which no sane person should do :)) and was not tested on other platforms than Linux, although I tried to code in some Windows compatibility. PS. If there are no objections to the packet capturing patch (http://lists.gnu.org/archive/html/qemu-devel/2007-12/msg00501.html), could somebody please apply it? Or if there are, please let me know so that I can make any necessary changes. Best regards ___ Support the World Aids Awareness campaign this month with Yahoo! For Good http://uk.promotions.yahoo.com/forgood/Index: block.c === RCS file: /sources/qemu/qemu/block.c,v retrieving revision 1.53 diff -u -r1.53 block.c --- block.c 24 Dec 2007 16:10:43 - 1.53 +++ block.c 30 Dec 2007 09:49:41 - @@ -35,6 +35,11 @@ #include #endif +#include +#include +#include +#include + #define SECTOR_BITS 9 #define SECTOR_SIZE (1 << SECTOR_BITS) @@ -123,6 +128,132 @@ } } +char *realpath_alloc(const char *path) +{ +int buff_len; +char *result; + +#ifdef PATH_MAX +buff_len = PATH_MAX; +#else +buff_len = pathconf(path, _PC_PATH_MAX); +if (buff_len <= 0) +buff_len = 4096; +#endif + +++buff_len; +result = (char*)malloc(buff_len * sizeof(char)); +if (!result) +return NULL; + +realpath(path, result); +return result; +} + +char *get_relative_path(char *path, char *relative_to) +{ +char *path_real; +char *path_prefix; +char *path_real_suffix; +char *path_real_to; +char *path_real_to_suffix; +char *result; +int prefix_len, i, slash_count; +char *string_end; +char path_separator; +#ifdef _WIN32 +path_separator = '\\'; +#else +path_separator = '/'; +#endif + +if (NULL == path || NULL == relative_to) +return NULL; + +printf(">>>%s\n>>>%s\n", path, relative_to); + +path_real = realpath_alloc(path); +if (!path_real) + return NULL; +path_real_to = realpath_alloc(relative_to); +if (!path_real_to) +{ + free(path_real); + return NULL; +} + +if (0 == strcmp(path_real, path_real_to)) +{ +free(path_real); +free(path_real_to); + + //the two directories are equal, the relative path is an empty string + result = (char*)malloc(sizeof(char)); + *result = '\0'; + return result; +} + +result = NULL; + +//eliminate the common prefix +for (prefix_len = 0; + path_real[prefix_len] != '\0' && + path_real_to[prefix_len] != '\0' && + path_real[prefix_len] == path_real_to[prefix_len]; + ++prefix_len); + +path_prefix = path_real; +path_real_suffix = path_real + prefix_len; +while ('\0' != *path_real_suffix && +#ifdef _WIN32 +('/' == *path_real_suffix || '\\' == *path_real_suffix) +#else +('/' == *path_real_suffix) +#endif +) { *path_real_suffix++ = '\0'; } + +path_real_to_suffix = path_real_to + prefix_len; +while ('\0' != *path_real_to_suffix && +#ifdef _WIN32 +('/' == *path_real_to_suffix || '\\' == *path_real_to_suffix) +#else +('/' == *path_real_to_suffix) +#endif +) { *path_real_to_suffix++ = '\0'; } + +slash_count = 0; +for (i = 0; '\0' != path_real_to_suffix[i]; ++i) +#ifdef _WIN32 +if ('/' == path_real_to_suffix[i] || '\\' == path_real_to_suffix[i]) +#else +if ('/' == path_real_to_suffix[i]) +#endif + ++slash_count; + if ('\0' != *path_real_to_suffix) ++slash_count; +result = (char*)malloc(sizeof(char) * (4 + 3 * slash_count + strlen(path_real_suffix))); + +string_end = result; +for (i = 0; i < slash_count; ++i) +{ +if (i > 0) +*string_end++ = path_separator; +*string_end++ = '.'; +*string_end++ = '.'; +} +if (0 == slash_count) +*string_end++ = '.'; +if ('\0' != *path_real_suffix) +{ +*string_end++ = p
[Qemu-devel] [PATCH] Capture network traffic
W00t, my first patch got applied :) Thank you. Here goes version 0.3 of my packet capture patch. I rewritten it to be a custom VLANClient which implements the capturing part in its fd_read proceudre, rather than adding additional properties to the VLAN structure. Monitor support is also present. Also, could somebody please give me any hints regarding my questions described here: http://lists.gnu.org/archive/html/qemu-devel/2007-12/msg00296.html (Qemu architectural questions)? Any pointers would be greatly appreciated. Best regards. __ Sent from Yahoo! Mail - a smarter inbox http://uk.mail.yahoo.com Index: vl.c === RCS file: /sources/qemu/qemu/vl.c,v retrieving revision 1.388 diff -u -r1.388 vl.c --- vl.c 17 Dec 2007 04:42:28 - 1.388 +++ vl.c 18 Dec 2007 07:30:26 - @@ -237,6 +237,19 @@ static CPUState *next_cpu; static int event_pending = 1; +/* File header which needs to be written at the start of each PCAP file*/ +static const PCAPHeader pcap_file_header = { +0xa1b2c3d4, /* Magic header - used to determine file endianess */ +2, /* Version major */ +4, /* Version minor */ +0, +0, +MAX_CAPTURED_PACKET_SIZE, +1 /* Ethernet */ +}; +/* Used to return in case a memory allocation fails (because obviously we can't allocate memory then!) */ +static char *pcap_memory_error = "Failed to allocate memory"; + #define TFR(expr) do { if ((expr) != -1) break; } while (errno == EINTR) /***/ @@ -4669,6 +4682,7 @@ char buf[1024]; int vlan_id, ret; VLANState *vlan; +char *error_message; p = str; q = device; @@ -4788,6 +4802,15 @@ } vlan->nb_host_devs++; } else +if (!strcmp(device, "capture")) { +error_message = pcap_add_capture(vlan_id, (char*)get_param_value(buf, sizeof(buf), "file", p)); +if (error_message) { +fprintf(stderr, "%s\n", error_message); +free(error_message); +return -1; +} +ret = 0; +} else { fprintf(stderr, "Unknown network device: %s\n", device); return -1; @@ -4799,6 +4822,152 @@ return ret; } +/* VLAN Packet capture */ + +static void pcap_receive(void *opaque, const uint8_t *buf, int size) { +PCAPStateInfo *pcap_state; + +pcap_state = (PCAPStateInfo*)opaque; + +pcap_state->packet_header.timestamp_sec = time(NULL); +if (pcap_state->packet_header.timestamp_sec == pcap_state->last_packet_time) { +if (pcap_state->packet_header.timestamp_usec < 100) +++pcap_state->packet_header.timestamp_usec; +} else { +pcap_state->packet_header.timestamp_usec = 0; +pcap_state->last_packet_time = pcap_state->packet_header.timestamp_sec; +} + +pcap_state->packet_header.orig_len = size; +pcap_state->packet_header.saved_len = (size > MAX_CAPTURED_PACKET_SIZE) ? MAX_CAPTURED_PACKET_SIZE : size; +write(pcap_state->fh, &pcap_state->packet_header, sizeof(PCAPPacketHeader)); +write(pcap_state->fh, buf, pcap_state->packet_header.saved_len); +} + +/* Add capture to a given VLAN. */ +/* Returns NULL on success, the error message in case of an error. */ +/* If an error message is returned, the caller must "free" it */ +char* pcap_add_capture(int vlan_id, const char *filename) +{ +VLANState *vlan; +VLANClientState *vlan_client; +char *error_message; +PCAPStateInfo *pcap_state; + +if (NULL == filename) +filename = DEFAULT_CAPTURE_FILENAME; + +for(vlan = first_vlan; vlan != NULL; vlan = vlan->next) +if (vlan_id == vlan->id) +break; +if (!vlan) { +asprintf(&error_message, "Error locating VLAN %d to attach for capture.", vlan_id); +return error_message; +} + +//check if already capturing +vlan_client = vlan->first_client; +while (NULL != vlan_client) { +if (pcap_receive == vlan_client->fd_read) { +asprintf(&error_message, "VLAN %d is already capturing. " +"Only one capture per VLAN is possible.", vlan_id); +return error_message; +} +vlan_client = vlan_client->next; +} + +//not capturing, try to start / attach it +pcap_state = qemu_mallocz(sizeof(PCAPStateInfo)); +if (!pcap_state) +return pcap_memory_error; +vlan_client = qemu_new_vlan_client(vlan, &pcap_receive, NULL, pcap_state); +if (!vlan_client) { +free(pcap_state); +return pcap_memory_error; +} + +pcap_state->fh = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0644); +if (pcap_state->fh < 0) { +free(pcap_state); +free(vlan_client); + +asprintf(&error_message, "Failed to open capture file \"%s\": %d\n", filename, errno);
Re: [Qemu-devel] [PATCH] Fix compilation with Cygwin
I just want to confirm that the fix works also for MinGW. At first I dind't like the word "type" and would have preferred something like "if_type", but I realized that drives[i].type is just as readable as drives[i].if_type. - Original Message From: Hervé Poussineau <[EMAIL PROTECTED]> To: qemu-devel@nongnu.org Sent: Thursday, 13 December, 2007 9:42:07 AM Subject: [Qemu-devel] [PATCH] Fix compilation with Cygwin Hi, Cygwin compiler doesn't seem to like variables/structure members which are named "interface". This patch renames them to "type". Hervé __ Sent from Yahoo! Mail - a smarter inbox http://uk.mail.yahoo.com
[Qemu-devel] Windows build broken
Trying to build the current CVS Head with Mingw under windows, the result is the following error message: In file included from tap-win32.c:31: sysemu.h:125: error: syntax error before ';' token sysemu.h:137: error: syntax error before ',' token sysemu.h:138: error: syntax error before ')' token make: *** [tap-win32.o] Error 1 __ Sent from Yahoo! - the World's favourite mail http://uk.mail.yahoo.com
[Qemu-devel] An architectural question
Hello all, First of all I want to apologize for this mail and hope that I won't wast to much of your valuable time hacking on Qemu ;-). My goal is to implement a tracing system in Qemu, which would suspend the emulation at certain points (determined by linear addresses), dump some information from the memory and resume the execution. My first attempt was to "hijack" the breakpoint system, by doing the following: I've placed a breakpoint at the address of the instruction I wanted to trace and inside of the main_loop function when the EXCP_DEBUG exception occurred I performed the logging after which I called vm_start to resume the operation. However the performance was abyssal... My next idea would be to replace the opcode generated for the debug point with a procedure call (which would, instead of stopping the emulation, perform the logging and let the emulation go on its way). I've implemented a prototype for this by placing the address of the callback procedure inside of the CPUState structure (given that this structure is accessible to the code fragments), however it segfaults. My questions would be: - What would be the most optimal way to implement this? (Something that would allow the OS to run at a usable speed inside of the emulated machine...) - What does the kernel level acceleration layer (kqemu) exactly do? Does it create a separate address space (page directory) for the emulated process? Is it possible to perform a callback from the code running under kqemu into a procedure defined in Qemu the way I'm trying to do it (I see multiple possible obstacles here: is the code run in a separate address space? is it run with a separate privilege level - ring 0/1 vs ring 3)? - Do I understand correctly that when using full acceleration (ie. -kernel-kqemu), the dynamic translation (ie. guest code -> translation block) is limited to code segments which cause exceptions? If so, do I infer correctly that, unless the code I wish to trace is of such type, it will never have the chance to call the logging procedure (because it would be included in the translation block)? Best regards and thank you for your time and patience. ___ Support the World Aids Awareness campaign this month with Yahoo! For Good http://uk.promotions.yahoo.com/forgood/
Re: [Qemu-devel] [PATCH] Capture network traffic to a tcpdump file - updated
The use case I need it for is for honeypot-like systems. Ie. the system starts from a snapshot and accesses links / runs executables while observing the behaviour. For this use case it is the best if it is setable from the command line. ___ Yahoo! Answers - Got a question? Someone out there knows the answer. Try it now. http://uk.answers.yahoo.com/
[Qemu-devel] [PATCH] Capture network traffic to a tcpdump file - updated
Here goes v0.2 for my patch :-) Changes - now the option is a separate command line switch: -net capture,vlan=2,file=test.pcap - it is also available from the monitor - added some more constants / defines to avoid repeating portions of the code __ Sent from Yahoo! Mail - a smarter inbox http://uk.mail.yahoo.com Index: vl.c === RCS file: /sources/qemu/qemu/vl.c,v retrieving revision 1.377 diff -u -r1.377 vl.c --- vl.c 6 Dec 2007 22:11:20 - 1.377 +++ vl.c 10 Dec 2007 10:28:35 - @@ -237,6 +237,17 @@ static CPUState *next_cpu; static int event_pending; +/* File header which needs to be written at the start of each PCAP file*/ +static const PCAPHeader pcap_file_header = { +0xa1b2c3d4, +2, +4, +0, +0, +MAX_CAPTURED_PACKET_SIZE, +1 /* Ethernet */ +}; + #define TFR(expr) do { if ((expr) != -1) break; } while (errno == EINTR) /***/ @@ -3588,6 +3599,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 +3648,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); @@ -4641,7 +4670,8 @@ char device[64]; char buf[1024]; int vlan_id, ret; -VLANState *vlan; +VLANState *vlan; +const char *capture_file_name; p = str; q = device; @@ -4761,6 +4791,27 @@ } vlan->nb_host_devs++; } else +if (!strcmp(device, "capture")) { +if (vlan->pcap_fh >= 0) { + fprintf(stderr, "vlan %d has already a capture file defined! " + "Can't have multiple capture files for the same vlan\n", vlan->id); + return -1; +} + +capture_file_name = DEFAULT_CAPTURE_FILENAME; +if (get_param_value(buf, sizeof(buf), "file", p)) +capture_file_name = buf; + +vlan->pcap_fh = open(capture_file_name, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0644); + if (vlan->pcap_fh < 0) { + fprintf(stderr, "Failed to open capture file \"%s\": %d\n", capture_file_name, errno); + return -1; + } + + write(vlan->pcap_fh, &pcap_file_header, sizeof(pcap_file_header)); + + ret = 0; +} else { fprintf(stderr, "Unknown network device: %s\n", device); return -1; @@ -4784,6 +4835,59 @@ } } +void do_net_capture (const char *path, +int has_vlan, int vlan_id) +{ +VLANState *vlan; + +vlan_id = (has_vlan) ? vlan_id : 0; +vlan = qemu_find_vlan(vlan_id); +if (!vlan) { +term_printf("Failed to find vlan %d\n", vlan_id); +return; +} + +if (vlan->pcap_fh >= 0) { + term_printf("Vlan %d is already capturing!\n", vlan_id); + return; +} + +vlan->pcap_fh = open(path, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0644); + if (vlan->pcap_fh < 0) { + term_printf("Failed to open capture file \"%s\": %d\n", path, errno); + return; + } + + vlan->last_packet_time = 0; + write(vlan->pcap_fh, &pcap_file_header, sizeof(pcap_file_header)); +} + +void do_stop_net_capture(int has_vlan, int vlan_id) +{ +VLANState *vlan; + +if (has_vlan) { +vlan = qemu_find_vlan(vlan_id); +if (!vlan) { +term_printf("Failed to find vlan %d\n", vlan_id); +return; +} + +if (vlan->pcap_fh < 0) { +term_printf("Vlan %d is not capturing!\n", vlan_id); +return; +} + +close(vlan->pcap_fh); +vlan->pcap_fh = -1; +vlan->last_packet_time = 0; +} else { +for(vlan = first_vlan; vlan != NULL; vlan = vlan->next) +if (vlan->pcap_fh >= 0) +close(vlan->pcap_fh); +} +} + #define HD_ALIAS "file=\"%s\",index=%d,media=disk" #ifdef TARGET_PPC #define CDROM_ALIAS "index=1,media=cdrom"
Re: [Qemu-devel] [PATCH] Capture traffic to a pcap file
>> 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 >> > I like the idea but I think it would be more useful as a monitor command > similar to how the audio capture command works already. Good idea. I will create a patch to update that feature too (but the command line should be left in IMHO, because there are use-cases where you would want to start such a capture in an automated way - ie. a honeypot) ___ Support the World Aids Awareness campaign this month with Yahoo! For Good http://uk.promotions.yahoo.com/forgood/
[Qemu-devel] [PATCH] Capture traffic to a pcap file
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);
[Qemu-devel] [PATCH] Support alternative formats for MAC addresses
The attached patch modifies the parser function for the mac addresses (ie. -net nic,macaddr=XX) in the following ways: - the accepted separators now include "-", because on Windows it is common to write a MAC addresses separated by dashes (ie. 54-32-00-12-34-56) - it supports specifying the lower part of the MAC address (ie. the last three bytes) as an integer number (so that you can say -net nic,macaddr=0x1234, which would result in the mac address of 54-32-00-00-12-34). This simplifies the situations where you want to connect together multiple Qemu virtual machines and you want an easy way to ensure that they network cards don't have colliding MAC addresses (simpler than having to retype the whole address) Any comments are welcome. __ 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 4 Dec 2007 22:58:58 - @@ -3452,18 +3452,32 @@ static int parse_macaddr(uint8_t *macaddr, const char *p) { int i; -for(i = 0; i < 6; i++) { -macaddr[i] = strtol(p, (char **)&p, 16); -if (i == 5) { -if (*p != '\0') -return -1; -} else { -if (*p != ':') -return -1; -p++; -} +char *last_char; +long int offset; + +errno = 0; +offset = strtol(p, &last_char, 0); +if ((0 == errno) && ('\0' == *last_char) && (offset >= 0) && (offset <= 0xFF)) { + macaddr[3] = (offset & 0xFF) >> 16; + macaddr[4] = (offset & 0xFF00) >> 8; + macaddr[5] = offset & 0xFF; + return 0; +} else { + for(i = 0; i < 6; i++) { + macaddr[i] = strtol(p, (char **)&p, 16); + if (i == 5) { + if (*p != '\0') + return -1; + } else { + if (*p != ':' && *p != '-') + return -1; + p++; + } + } + return 0; } -return 0; + +return -1; } static int get_str_sep(char *buf, int buf_size, const char **pp, int sep)
Re: [Qemu-devel] [PATCH 1/2] Add "directio" parameter to "-drive"
Le mercredi 28 novembre 2007 à 14:24 +, Samuel Thibault a écrit : > Hi, > > Laurent Vivier, le Wed 28 Nov 2007 15:02:50 +0100, a écrit : > > +ret = posix_memalign((void**)&buf, 0x200, 512); > > For making this more easily portable, maybe it should be a new > qemu_memalign() function? Also, the alignment may probably be better as > a global macro, since the alignment requirements depend on the OS. > I think O_DIRECT is linux specific Windows has something similar (I think). Check out the FILE_FLAG_WRITE_THROUGH and FILE_FLAG_NO_BUFFERING flags for the CreateFile API call under Win32 (http://msdn2.microsoft.com/en-us/library/aa363858.aspx) Best regards. ___ Yahoo! Answers - Got a question? Someone out there knows the answer. Try it now. http://uk.answers.yahoo.com/
Re: [Qemu-devel] [PATCH] Dump traffic to pcap file - update
You're absolutely right. Attached a corrected version. - Original Message From: Blue Swirl <[EMAIL PROTECTED]> To: qemu-devel@nongnu.org Sent: Sunday, 1 July, 2007 9:08:00 PM Subject: Re: [Qemu-devel] [PATCH] Dump traffic to pcap file - update On 7/1/07, Balazs Attila-Mihaly (Cd-MaN) <[EMAIL PROTECTED]> wrote: > Attached you find an updated version of my patch to dump the traffic on a > given interface to a tcpdump file. The changes are: This part is not right: +void pcap_close_files() +{ +int i; +for (i = 0; i <= nb_nics; i++) <= should be <. ___ Yahoo! Answers - Got a question? Someone out there knows the answer. Try it now. http://uk.answers.yahoo.com/ 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 - 1.317 +++ vl.c 1 Jul 2007 19:01:14 - @@ -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 < ) 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 > 0x) ? 0x : 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 = 0x; + hdr.network = 1; + write(vlan->pcap_file, &hdr, sizeof(hdr)); + } nd->vlan = vlan; nb_nics++; vlan->nb_guest_devs++; @@ -6624,7 +6677,7 @@ "-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" #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 - 1.255 +++ vl.h 1 Jul 2007 19:01:16 - @@ -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 */ +
[Qemu-devel] [PATCH] Macaddr parsing
Hello all. Attached is an other patch (against the CVS) to allow for more flexible mac address parsing from the command line. Specifically it allows: -using the '-' as separator (as Windows uses it) -using no separator at all (just 12 hexadecimal characters in a row) - again Windows uses this style in some configuration dialogs -using an offset from the default address (like +2 or -10). This is useful for quickly bringing up a virtual lan without having to remember the base macaddr, you just specify different offsets (an other option would be to use mac addresses like 12:34:56:78:9A:BC which are easy to remember, however I found that WinXP for example does not react well - duplicate packets, no conectivity at the IP level although the ARP level is fine, etc - if the OUI - the first 3 bytes of the mac address - is incorrect) Also, there was a suggestion on the list some time ago to use the crc of the path to the disk image as part of the macaddr to ensure uniqueness. If people feel that this would be useful, I'm happy to provide a patch. Best regards ___ Yahoo! Mail is the world's favourite email. Don't settle for less, sign up for your free account today http://uk.rd.yahoo.com/evt=44106/*http://uk.docs.yahoo.com/mail/winter07.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 - 1.317 +++ vl.c 1 Jul 2007 11:42:53 - @@ -3020,21 +3020,66 @@ } } +static inline int is_hex_char(char c) +{ + return (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F') || (c >= '0' && c <= '9'); +} + static int parse_macaddr(uint8_t *macaddr, const char *p) { -int i; -for(i = 0; i < 6; i++) { -macaddr[i] = strtol(p, (char **)&p, 16); -if (i == 5) { -if (*p != '\0') -return -1; -} else { -if (*p != ':') -return -1; -p++; -} -} -return 0; + if (NULL == p) + return -1; + + if ('-' == *p || '+' == *p) + { + /* an offset relative to the default address */ + char *endptr; + int offset = strtol(p, (char**)&endptr, 0); + if ('\0' != *endptr) + return -1; + /* convert the macaddr to 64 bit num, add the offset and convert it back */ + uint64_t macaddr_l = ((uint64_t)macaddr[0] << 40UL) + ((uint64_t)macaddr[1] << 32UL) + + ((uint64_t)macaddr[2] << 24UL) + ((uint64_t)macaddr[3] << 16UL) + ((uint64_t)macaddr[4] << 8UL) + + ((uint64_t)macaddr[5]); + macaddr_l += offset; + macaddr[0] = (uint8_t)((macaddr_l >> 40UL) & 0xFF); + macaddr[1] = (uint8_t)((macaddr_l >> 32UL) & 0xFF); + macaddr[2] = (uint8_t)((macaddr_l >> 24UL) & 0xFF); + macaddr[3] = (uint8_t)((macaddr_l >> 16UL) & 0xFF); + macaddr[4] = (uint8_t)((macaddr_l >> 8UL) & 0xFF); + macaddr[5] = (uint8_t)((macaddr_l >> 0UL) & 0xFF); + } + else if (is_hex_char(*p)) + { + /* a full mac address - hopefully :) */ + int mac_i = 0; + while ('\0' != *p) + { + /* skip separator chars */ + while ( ('\0' != *p) && (':' == *p || '-' == *p) ) p++; + char hex_chars[3]; hex_chars[2] = '\0'; + /* get two hexdec chars and parse it */ + if ( is_hex_char(*p) && is_hex_char(*(p+1)) ) + { +hex_chars[0] = *p; hex_chars[1] = *(p+1); +macaddr[mac_i] = strtol(hex_chars, NULL, 16); +p += 2; mac_i++; +/* the string should contain only 6 pairs */ +if (mac_i >= 6 && *p != '\0') + return -1; + } + else + { +return -1; + } + } + } + else + { + /* error, unexpected character */ + return -1; + } + return 0; } static int get_str_sep(char *buf, int buf_size, const char **pp, int sep)
[Qemu-devel] [PATCH] Dump traffic to pcap file - update
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.htmlIndex: 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 - 1.317 +++ vl.c 1 Jul 2007 08:44:43 - @@ -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 < ) 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 > 0x) ? 0x : 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 = 0x; + hdr.network = 1; + write(vlan->pcap_file, &hdr, sizeof(hdr)); + } nd->vlan = vlan; nb_nics++; vlan->nb_guest_devs++; @@ -6624,7 +6677,7 @@ "-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" #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 - 1.255 +++ vl.h 1 Jul 2007 08:44:44 - @@ -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 */ +
Re: [Qemu-devel] QEMU License and proprietary hardware
I must prefix this with the fact that IANAL, but as I understand it, you must release the source code only if you distribute that modified system (with GPL v2). That is, if you use this system internally in you company, you don't have to provide your modifications. But if you, for example, provide your clients with the modified version, you have the obligation to provide them (your clients, not the Qemu community in general) also with the complete source code, after which they have the liberty to redistribute the source code under the GPL. One solution would be (again, IANAL, so please check with a real lawyer :D), is to create an interface to the code you wish to include and put the proprietary code in a dynamically linked library which exposes this interface. In this case IMHO you have to provide only the code which implements the interface in Qemu and loads the shared library, and you would have no obligation regarding the code in the shared library. - Original Message From: Armbrost Failsafe <[EMAIL PROTECTED]> To: qemu-devel@nongnu.org Sent: Thursday, 21 June, 2007 2:28:53 PM Subject: [Qemu-devel] QEMU License and proprietary hardware We are looking into using QEMU as the base for a model of a custom system featuring some custom ASICs. But licensing issues are halting the process right now. Does anyone know what happens license-wise if we create a model of proprietary hardware using QEMU? Is that model automatically covered by the GPL and thus we have to give to anyone who asks about it? It is clear that if we keep it internal, it is OK. But anyone outside of our organization is to use it, shouldn't they automatically be entitled to receive the entire source of QEMU, including our models of proprietary devices? Even if these are developed from scratch without using any existing source code for devices? /armbrost ___ Yahoo! Mail is the world's favourite email. Don't settle for less, sign up for your free account today http://uk.rd.yahoo.com/evt=44106/*http://uk.docs.yahoo.com/mail/winter07.html
[Qemu-devel] [PATCH] Constants in command line definition
Hello, this is me again. In the last time I forgot to specify that the patches are against the current CVS contents. This is a small patch which replaces the numeric values "1" in the "qemu_options" structure (which defines the command line format) with the constant HAS_ARG. I feel that this improves readibility of the code, since having both 1 and the constant HAS_ARG present implies that they have different meaning (0 doesn't need to be replaced with any symbolic name imho, since it is usually associated with "nothing" anyways). Best regards, Cd-MaN ___ All New Yahoo! Mail – Tired of unwanted email come-ons? Let our SpamGuard protect you. http://uk.docs.yahoo.com/nowyoucan.htmlIndex: vl.c === RCS file: /sources/qemu/qemu/vl.c,v retrieving revision 1.306 diff -u -r1.306 vl.c --- vl.c 10 Jun 2007 19:21:04 - 1.306 +++ vl.c 21 Jun 2007 19:34:09 - @@ -6821,10 +6821,10 @@ #endif { "localtime", 0, QEMU_OPTION_localtime }, { "std-vga", 0, QEMU_OPTION_std_vga }, -{ "echr", 1, QEMU_OPTION_echr }, -{ "monitor", 1, QEMU_OPTION_monitor }, -{ "serial", 1, QEMU_OPTION_serial }, -{ "parallel", 1, QEMU_OPTION_parallel }, +{ "echr", HAS_ARG, QEMU_OPTION_echr }, +{ "monitor", HAS_ARG, QEMU_OPTION_monitor }, +{ "serial", HAS_ARG, QEMU_OPTION_serial }, +{ "parallel", HAS_ARG, QEMU_OPTION_parallel }, { "loadvm", HAS_ARG, QEMU_OPTION_loadvm }, { "full-screen", 0, QEMU_OPTION_full_screen }, #ifdef CONFIG_SDL
[Qemu-devel] [PATCH] Dump traffic on virtual network to pcap file
Hello all. As promised I'll start to provide patches for modifications I've made to the Qemu source code as part of the project. Attached you find the first of these patches - an option to dump the traffic on a virtual interface to a tcpdump compatible file. I welcome any feedback since this is the first time I contributed actual code to an open source project. My main concern is that the code performing the actual dump is bound to the vlan not to the interface (it does the saving in the "qemu_send_packet" procedure). While this is generally speaking ok (since there is usually one vlan per interface per virtual computer), I welcome any suggestion where the code should be put. Best regards, Cd-MaN ___ New Yahoo! Mail is the ultimate force in competitive emailing. Find out more at the Yahoo! Mail Championships. Plus: play games and win prizes. http://uk.rd.yahoo.com/evt=44106/*http://mail.yahoo.net/uk Index: vl.c === RCS file: /sources/qemu/qemu/vl.c,v retrieving revision 1.306 diff -u -r1.306 vl.c --- vl.c 10 Jun 2007 19:21:04 - 1.306 +++ vl.c 21 Jun 2007 19:13:32 - @@ -3157,6 +3157,12 @@ while (*pvlan != NULL) pvlan = &(*pvlan)->next; *pvlan = vlan; + + //initialize the packet capture options + vlan->pcap_file = NULL; + vlan->last_written_time = 0; + vlan->packet_serial_num = 0; + return vlan; } @@ -3200,6 +3206,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 < ) 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 > 0x) ? 0x : size; + fwrite(&pcap_record_header, sizeof(pcap_record_header), 1, vlan->pcap_file); + fwrite(buf, pcap_record_header.incl_len, 1, vlan->pcap_file); + } #if 0 printf("vlan %d send:\n", vlan->id); @@ -4194,6 +4216,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 = fopen(buf, "wb"); + 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 = 0x; + hdr.network = 1; + fwrite(&hdr, sizeof(hdr), 1, vlan->pcap_file); + } nd->vlan = vlan; nb_nics++; vlan->nb_guest_devs++; @@ -6585,7 +6625,7 @@ "-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=file]\n" "create a new Network Interface Card and connect it to VLAN 'n'\n" #ifdef CONFIG_SLIRP "-net user[,vlan=n][,hostname=host]\n" Index: vl.h === RCS file: /sources/qemu/qemu/vl.h,v retrieving revision 1.252 diff -u -r1.252 vl.h --- vl.h 18 Jun 2007 18:55:46 - 1.252 +++ vl.h 21 Jun 2007 19:14:11 - @@ -390,6 +390,12 @@ 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 + FILE *pcap_file; + time_t last_written_time; + int packet_serial_num; } VLANState; VLANState *qemu_find_vlan(int id); @@ -402,6 +408,24 @@ void qemu_handler_true(void *opaque); void do_info_network(void); +/* PCAP file structures */ + +typedef struct PCAPHeader { +unsigned int magic_number; /* magic number */ +unsigned short int version_major; /* major version number */ +unsigned short int version_minor; /* minor version number */ +int thiszone; /* GMT to local correction */ +unsigned int sigfigs;/* accuracy of timestamps */ +unsigned int snaplen;/* max length of captured packets, in octets */ +unsigned int network;/* data link type */ +} PCAPHeader; + +typedef struct PCAPRecordHeader { +unsigned int ts_sec; /* timestamp seconds */ +unsigned int ts_usec;/* timestamp microseconds */ +unsigned int incl_len; /* number of octets of pac
[Qemu-devel] A couple of question
Hello all. First of all I want to congratulate everybody on this list for the wonderful job s/he is doing. Qemu is the best Open Source emulator out there (and it is fast ;-) ). I'm using Qemu to build an automated malicious code analysis system and as such I would like to make some modifications: -create an option to dump all the traffic coming out of an interface in a tcpdump (pcap) file. I've managed to implement this (and if anyone is interested, I can provide a diff against the latest CVS, the changes being very localized and no more than 100 lines), however I have my doubts: I do the traffic logging in the qemu_send_packet function, which refers to VLAN's not to NIC's. Because of this I associated the structures needed for the dump (like the output file handle) with the VLANState structure, however maybe it would be more appropiate to associate it with a NICInfo structure (because it makes - usually - more sense to dump the traffic from one NIC rather than one VLAN imho), but I couln't find (a) any method to get the appropiate NICInfo structure inside of qemu_send_packet or (b) find a different function which has access to NICInfo. My first question would be: am I hooking at the right point? -modified the breakpoints to be stored in a hash structure (like this breakpoints[256][1024]) where the hash key is given by the least significant byte of the breakpoint address. I've done this because I intend to put a lot (and I mean a lot :-) ) of breakpoints. I also modified the watchpoint code in a similar manner. again, if you are interested I can provide a diff against the CVS. -Created an option to dump the sectors where there been writes to a file / console / etc (whatever qemu_chr_open supports). I've done this because after the execution of the malicious code I want to quickly asses which sectors have been written (again, if somebody would find something like this usefull, I can provide diffs). An other option would have been to create a difference disk over the basic image and take the list of sectors from the difference image (which obviously are present because they have been modified). However this approach has the drawback that it can't be used with snapshots. Specifically, I would like to do something like this [ base image (with a snapshot for quick startup) ] <-- [ diff image ] <-- Qemu However it seems that Qemu can read the snapshot only from the last image in the chain (diff image in the example). How hard is it to make this work with an arbitrary image from the chain? One obvious thing which needs to be done is making sure that the snapshot ID's / tag names are unique across the whole chain, but other than that how easy is to make this happen? -Also created an option to dump the program state (ie. variables from the stack) at certain points in the execution. My solution is the following: 1. Add a list of breakpoints right before main_loop(); (to the first_cpu) 2. In the main_loop function where it says "if (ret == EXCP_DEBUG) {", I added a function call to check if it is one of my breakpoints. 3. If so I log the data and return 1, otherwise 0. I check the return value and if it's 1, I do a "vm_start();" (this all is done after "vm_stop(EXCP_DEBUG);") However there seem to be a flaw in this approach and the code seem to enter in an infinite cycle. My theory is the following (which I hope somebody can confirm or prove wrong); -the execution hits the TB which contains the 0xCC (int 3) corresponding to the breakpoint -the int 3 is catched (before the instruction is executed) and control is transferred back to the main loop -the logging procedure gets called -when resuming the execution is started at the TB (because the instruction did not execute yet and needs to be executed), but because it contains a 0xCC, it again is thrown back to the main loop and so on. If my theory is right, then the breakpoint must be removed (at least temporarily) for the execution to continue. However there is no guarantee that I can get back control in timely fashion (for example at the next instruction) to insert the breakpoint back because of TB chaining, plus I'm concerned that such an add / remove would very quickly trash the TB cache. My questions would then be: 1. Is my assumption of what's going on correct? and 2. what can I do? for example one thing I though of was to set some flag when such a breakpoint is occured to ignore the next int 3 in the exception handler which catches it and gives back the control to the main loop. An other thing would be to dynamically patch the TB and replace 0xCC (int 3) with 0x90 (NOP). Of course this has the problem that to patch the TB must be located first and also the problem of when can the "back" patching occur. PS. I'm willing to provide the code for this part also (if somebody is interested), however it's still very alpha (it doesn't even work yet , as you can see from my questions :-)) PPS. If ther