qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH] Capture network traffic
@ 2007-12-18  7:36 Balazs Attila-Mihaly (Cd-MaN)
  2008-01-20  1:30 ` andrzej zaborowski
  0 siblings, 1 reply; 3+ messages in thread
From: Balazs Attila-Mihaly (Cd-MaN) @ 2007-12-18  7:36 UTC (permalink / raw)
  To: Qemu Devel

[-- Attachment #1: Type: text/plain, Size: 688 bytes --]

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

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: capture_network_traffic.patch --]
[-- Type: text/x-patch; name="capture_network_traffic.patch", Size: 10678 bytes --]

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 -0000	1.388
+++ vl.c	18 Dec 2007 07:30:26 -0000
@@ -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 < 1000000)
+            ++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);
+        return error_message;
+    }    
+    
+    //write the header to the file
+    write(pcap_state->fh, &pcap_file_header, sizeof(pcap_file_header));
+    
+    //success
+    return NULL;
+}
+
+/* (Tries to) remove capture from 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_remove_capture(int vlan_id)
+{
+    VLANState *vlan;
+    VLANClientState *vlan_client, *vlan_temp;
+    char *error_message;
+    PCAPStateInfo *pcap_state;
+    
+    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 remove capture.", vlan_id);
+        return error_message;
+    }
+    
+    vlan_client = NULL;
+    //two cases
+    //if the first vlan client is the pcap one
+    if (pcap_receive == vlan->first_client->fd_read) {
+        vlan_client = vlan->first_client;
+        vlan->first_client = vlan_client->next;
+    } else {
+        //search through the list
+        vlan_client = vlan->first_client;
+        while (NULL != vlan_client->next) {
+            if (pcap_receive == vlan_client->next->fd_read)
+                break;
+            vlan_client = vlan_client->next;
+        }
+        if (NULL != vlan_client && NULL != vlan_client->next) {
+            vlan_temp = vlan_client->next;
+            vlan_client->next = vlan_temp->next;
+            vlan_client = vlan_temp;
+        } else {
+            vlan_client = NULL;
+        }
+    }
+    
+    if (NULL == vlan_client) {
+        asprintf(&error_message, "No active capture found for VLAN %d", vlan_id);
+        return error_message;
+    }
+    
+    pcap_state = (PCAPStateInfo*)vlan_client->opaque;
+    close(pcap_state->fh);
+    free(pcap_state);
+    free(vlan_client);
+    
+    return NULL;
+}
+
+/* Removes the capture from all VLAN's */
+void pcap_remove_all_capture(void)
+{
+    VLANState *vlan;
+    char *error_message;
+    
+    for(vlan = first_vlan; vlan != NULL; vlan = vlan->next) {
+        error_message = pcap_remove_capture(vlan->id);
+        if (error_message) free(error_message);
+    }
+}
+
 void do_info_network(void)
 {
     VLANState *vlan;
@@ -7540,6 +7709,10 @@
            "                connect the vlan 'n' to another VLAN using a socket connection\n"
            "-net socket[,vlan=n][,fd=h][,mcast=maddr:port]\n"
            "                connect the vlan 'n' to multicast maddr and port\n"
+           "-net capture[,vlan=n][,file=filename]\n"
+           "                captures the traffic flowing through VLAN 'n' to the file\n"
+           "                'filename' in tcpdump format. In case filename is not specified,\n"
+           "                the capture will be saved to " DEFAULT_CAPTURE_FILENAME "\n"           
            "-net none       use it alone to have zero network devices; if no -net option\n"
            "                is provided, the default is '-net nic -net user'\n"
            "\n"
@@ -8948,6 +9121,9 @@
 
 	close(fd);
     }
+    
+    /* stop capturing packets (close capture files) on exit */
+    atexit(pcap_remove_all_capture);    
 
     main_loop();
     quit_timers();
@@ -8969,5 +9145,6 @@
         }
     }
 #endif
+    
     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	18 Dec 2007 07:30:26 -0000
@@ -1,6 +1,41 @@
 #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;
+
+#define MAX_CAPTURED_PACKET_SIZE 0xFFFF
+#define DEFAULT_CAPTURE_FILENAME "qemu.pcap"
+
+typedef struct {
+	uint32_t timestamp_sec;
+	uint32_t timestamp_usec;
+	uint32_t saved_len;
+	uint32_t orig_len;
+} PCAPPacketHeader;
+
+/* used to keep the state for the packet capture process */
+typedef struct {
+    //filehandle of the capture file
+    int fh;
+    time_t last_packet_time;
+    //defined here to avoid reallocation in the code
+    PCAPPacketHeader packet_header;
+} PCAPStateInfo;
+
+char* pcap_add_capture(int vlan_id, const char *filename);
+char* pcap_remove_capture(int vlan_id);
+void pcap_remove_all_capture(void);
+
 /* VLANs support */
 
 typedef struct VLANClientState VLANClientState;
Index: monitor.c
===================================================================
RCS file: /sources/qemu/qemu/monitor.c,v
retrieving revision 1.93
diff -u -r1.93 monitor.c
--- monitor.c	17 Dec 2007 03:15:51 -0000	1.93
+++ monitor.c	18 Dec 2007 07:30:27 -0000
@@ -1255,6 +1255,38 @@
 }
 #endif
 
+void do_net_capture (const char *path,
+                     int has_vlan, int vlan_id)
+{
+    char *error_message;
+    
+    if (!has_vlan) vlan_id = 0;
+    
+    error_message = pcap_add_capture(vlan_id, path);
+    if (error_message) {
+        term_printf("%s\n", error_message);
+        free(error_message);
+        return;
+    }
+    
+    return;
+}
+
+void do_stop_net_capture(int has_vlan, int vlan_id)
+{
+    char *error_message;
+    
+    if (has_vlan) {
+        error_message = pcap_remove_capture(vlan_id);
+        if (error_message) {
+            term_printf("%s\n", error_message);
+            free(error_message);
+            return;
+        }
+    } else
+        pcap_remove_all_capture();
+}
+
 static term_cmd_t term_cmds[] = {
     { "help|?", "s?", do_help,
       "[cmd]", "show the help" },
@@ -1326,6 +1358,10 @@
        "capture index", "stop capture" },
     { "memsave", "lis", do_memory_save,
       "addr size file", "save to disk virtual memory dump starting at 'addr' of size 'size'", },
+    { "netcapture", "si?", do_net_capture,
+      "[vlan]", "saves the traffic flowing through the given vlan to the file (default vlan=0)" },
+    { "stopnetcapture", "i?", do_stop_net_capture,
+      "[vlan]", "stops the capture of the specified vlan. if no vlan specified, stops all the capture" },            
     { NULL, NULL, },
 };
 

^ permalink raw reply	[flat|nested] 3+ messages in thread
* Re: [Qemu-devel] [PATCH] Capture network traffic
@ 2008-05-18 15:51 Balazs Attila-Mihaly (Cd-MaN)
  0 siblings, 0 replies; 3+ messages in thread
From: Balazs Attila-Mihaly (Cd-MaN) @ 2008-05-18 15:51 UTC (permalink / raw)
  To: qemu-devel

[-- Attachment #1: Type: text/plain, Size: 1658 bytes --]

First of all, I would like to thank you for taking the time to look over my patch. Sorry for not getting back to you sooner. I fixed most the mentioned issues and attached a diff which should apply cleanly to the current SVN HEAD.

> You can't cast the result of get_param_value() to char *
Fixed (I don't know what as was thinking...)

> Also I'm sure the use of asprintf() will upset the non-Linux-or-BSD users. 
AFAIK asprintf is quite standard (I know for a fact for example that the VC libraries implement it) and it is already used in the codebase. Are there known issues with it under some platforms? If so, shouldn't we create a wrapper function / emulation for it?

> I don't think you need to check for memory allocation failures (the message will not display anyway in such case, because monitor allocates memory for that).
Ok, I replaced it with exit(1), since I consider failure of memory allocation a major failure. Is this approach correct? Should I use a different exit code so that the user can identify the source of the failure?

> It will be nice if you can remove stray spaces on end of lines/empty lines.
Done. The perl script I hacked together for this can be downloaded from http://hype.free.googlepages.com/clean.pl in case anyone else needs it.

> The PCAPHeader struct probably should have a __packed__ attribute.
Good catch, I removed them

I also updated the documentation, although I'm not sure if I used the correct markup, so please check.

Best regards.



      __________________________________________________________
Sent from Yahoo! Mail.
A Smarter Email http://uk.docs.yahoo.com/nowyoucan.html

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: vlan_capture.diff --]
[-- Type: text/x-patch; name="vlan_capture.diff", Size: 11262 bytes --]

Index: vl.c
===================================================================
--- vl.c	(revision 4488)
+++ vl.c	(working copy)
@@ -240,6 +240,16 @@
 static CPUState *next_cpu;
 static int event_pending = 1;
 
+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 */
+};
+
 #define TFR(expr) do { if ((expr) != -1) break; } while (errno == EINTR)
 
 /***********************************************************/
@@ -3579,7 +3589,7 @@
     long int offset;
 
     errno = 0;
-    offset = strtol(p, &last_char, 0);    
+    offset = strtol(p, &last_char, 0);
     if (0 == errno && '\0' == *last_char &&
             offset >= 0 && offset <= 0xFFFFFF) {
         macaddr[3] = (offset & 0xFF0000) >> 16;
@@ -3598,7 +3608,7 @@
                 p++;
             }
         }
-        return 0;    
+        return 0;
     }
 
     return -1;
@@ -4798,6 +4808,7 @@
     char buf[1024];
     int vlan_id, ret;
     VLANState *vlan;
+    char *error_message;
 
     p = str;
     q = device;
@@ -4918,6 +4929,19 @@
         }
         vlan->nb_host_devs++;
     } else
+    if (!strcmp(device, "capture")) {
+        if (get_param_value(buf, sizeof(buf), "file", p) > 0) {
+            error_message = pcap_add_capture(vlan_id, buf);
+        } else {
+            error_message = pcap_add_capture(vlan_id, NULL);
+        }
+        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;
@@ -4929,6 +4953,148 @@
     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 < 1000000)
+            ++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));
+    vlan_client = qemu_new_vlan_client(vlan, &pcap_receive, NULL, pcap_state);
+    if (!vlan_client || !pcap_state)
+        exit(1);
+
+    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);
+        return error_message;
+    }
+
+    //write the header to the file
+    write(pcap_state->fh, &pcap_file_header, sizeof(pcap_file_header));
+
+    //success
+    return NULL;
+}
+
+/* (Tries to) remove capture from 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_remove_capture(int vlan_id)
+{
+    VLANState *vlan;
+    VLANClientState *vlan_client, *vlan_temp;
+    char *error_message;
+    PCAPStateInfo *pcap_state;
+
+    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 remove capture.", vlan_id);
+        return error_message;
+    }
+
+    vlan_client = NULL;
+    //two cases
+    //if the first vlan client is the pcap one
+    if (pcap_receive == vlan->first_client->fd_read) {
+        vlan_client = vlan->first_client;
+        vlan->first_client = vlan_client->next;
+    } else {
+        //search through the list
+        vlan_client = vlan->first_client;
+        while (NULL != vlan_client->next) {
+            if (pcap_receive == vlan_client->next->fd_read)
+                break;
+            vlan_client = vlan_client->next;
+        }
+        if (NULL != vlan_client && NULL != vlan_client->next) {
+            vlan_temp = vlan_client->next;
+            vlan_client->next = vlan_temp->next;
+            vlan_client = vlan_temp;
+        } else {
+            vlan_client = NULL;
+        }
+    }
+
+    if (NULL == vlan_client) {
+        asprintf(&error_message, "No active capture found for VLAN %d", vlan_id);
+        return error_message;
+    }
+
+    pcap_state = (PCAPStateInfo*)vlan_client->opaque;
+    close(pcap_state->fh);
+    free(pcap_state);
+    free(vlan_client);
+
+    return NULL;
+}
+
+/* Removes the capture from all VLAN's */
+void pcap_remove_all_capture(void)
+{
+    VLANState *vlan;
+    char *error_message;
+
+    for(vlan = first_vlan; vlan != NULL; vlan = vlan->next) {
+        error_message = pcap_remove_capture(vlan->id);
+        if (error_message) free(error_message);
+    }
+}
+
 void do_info_network(void)
 {
     VLANState *vlan;
@@ -7219,6 +7385,10 @@
            "                connect the vlan 'n' to another VLAN using a socket connection\n"
            "-net socket[,vlan=n][,fd=h][,mcast=maddr:port]\n"
            "                connect the vlan 'n' to multicast maddr and port\n"
+           "-net capture[,vlan=n][,file=filename]\n"
+           "                captures the traffic flowing through VLAN 'n' to the file\n"
+           "                'filename' in tcpdump format. In case filename is not specified,\n"
+           "                the capture will be saved to " DEFAULT_CAPTURE_FILENAME "\n"
            "-net none       use it alone to have zero network devices; if no -net option\n"
            "                is provided, the default is '-net nic -net user'\n"
            "\n"
@@ -7941,7 +8111,7 @@
                 {
                     /* Could easily be extended to 64 devices if needed */
                     const char *p;
-                    
+
                     boot_devices_bitmap = 0;
                     for (p = boot_devices; *p != '\0'; p++) {
                         /* Allowed boot devices are:
Index: net.h
===================================================================
--- net.h	(revision 4488)
+++ net.h	(working copy)
@@ -34,6 +34,41 @@
 
 void do_info_network(void);
 
+/* PCAP support */
+/* source: http://wiki.wireshark.org/Development/LibpcapFileFormat */
+typedef struct __attribute__ ((__packed__)) {
+    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;
+
+#define MAX_CAPTURED_PACKET_SIZE 0xFFFF
+#define DEFAULT_CAPTURE_FILENAME "qemu.pcap"
+
+typedef struct __attribute__ ((__packed__)) {
+	uint32_t timestamp_sec;
+	uint32_t timestamp_usec;
+	uint32_t saved_len;
+	uint32_t orig_len;
+} PCAPPacketHeader;
+
+/* used to keep the state for the packet capture process */
+typedef struct {
+    //filehandle of the capture file
+    int fh;
+    time_t last_packet_time;
+    //defined here to avoid reallocation in the code
+    PCAPPacketHeader packet_header;
+} PCAPStateInfo;
+
+char* pcap_add_capture(int vlan_id, const char *filename);
+char* pcap_remove_capture(int vlan_id);
+void pcap_remove_all_capture(void);
+
 /* NIC info */
 
 #define MAX_NICS 8
Index: qemu-doc.texi
===================================================================
--- qemu-doc.texi	(revision 4488)
+++ qemu-doc.texi	(working copy)
@@ -666,6 +666,11 @@
 /path/to/linux ubd0=/path/to/root_fs eth0=mcast
 @end example
 
+@item -net capture[,vlan=@var{n}][,file=@var{file}]
+Captures the traffic flowing through VLAN @var{n} to @var{file}
+in tcpdump format. In case @var{file} is not specified,
+the capture will be saved to qemu.pcap
+
 @item -net none
 Indicate that no network devices should be configured. It is used to
 override the default configuration (@option{-net nic -net user}) which
Index: monitor.c
===================================================================
--- monitor.c	(revision 4488)
+++ monitor.c	(working copy)
@@ -750,7 +750,7 @@
     FILE *f;
     uint32_t l;
     uint8_t buf[1024];
-    target_phys_addr_t addr = GET_TPHYSADDR(valh, vall); 
+    target_phys_addr_t addr = GET_TPHYSADDR(valh, vall);
 
     f = fopen(filename, "wb");
     if (!f) {
@@ -1311,6 +1311,38 @@
 }
 #endif
 
+void do_net_capture (const char *path,
+                     int has_vlan, int vlan_id)
+{
+    char *error_message;
+
+    if (!has_vlan) vlan_id = 0;
+
+    error_message = pcap_add_capture(vlan_id, path);
+    if (error_message) {
+        term_printf("%s\n", error_message);
+        free(error_message);
+        return;
+    }
+
+    return;
+}
+
+void do_stop_net_capture(int has_vlan, int vlan_id)
+{
+    char *error_message;
+
+    if (has_vlan) {
+        error_message = pcap_remove_capture(vlan_id);
+        if (error_message) {
+            term_printf("%s\n", error_message);
+            free(error_message);
+            return;
+        }
+    } else
+        pcap_remove_all_capture();
+}
+
 static term_cmd_t term_cmds[] = {
     { "help|?", "s?", do_help,
       "[cmd]", "show the help" },
@@ -1390,6 +1422,10 @@
     { "nmi", "i", do_inject_nmi,
       "cpu", "inject an NMI on the given CPU", },
 #endif
+    { "netcapture", "si?", do_net_capture,
+      "[vlan]", "saves the traffic flowing through the given vlan to the file (default vlan=0)" },
+    { "stopnetcapture", "i?", do_stop_net_capture,
+      "[vlan]", "stops the capture of the specified vlan. if no vlan specified, stops all the capture" },
     { NULL, NULL, },
 };
 

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2008-05-18 15:51 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-12-18  7:36 [Qemu-devel] [PATCH] Capture network traffic Balazs Attila-Mihaly (Cd-MaN)
2008-01-20  1:30 ` andrzej zaborowski
  -- strict thread matches above, loose matches on Subject: below --
2008-05-18 15:51 Balazs Attila-Mihaly (Cd-MaN)

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).