[libvirt] [PATCH 2/2] Add the command iface-dumptraffic to virsh

Hendrik Schwartke hendrik at os-t.de
Wed Jul 25 13:56:53 UTC 2012


The purpose of the iface-dumptraffic command is to sniff network
traffic on a (remote) interface.
E.g. "virsh iface-dumptraffic virbr0 icmp --promisc | tcpdump -n -r -"
prints all icmp pakets on stdout.
---
 tools/virsh.c |   84 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 84 insertions(+)

diff --git a/tools/virsh.c b/tools/virsh.c
index 1e00049..6024501 100644
--- a/tools/virsh.c
+++ b/tools/virsh.c
@@ -9253,6 +9253,88 @@ cmdInterfaceName(vshControl *ctl, const vshCmd *cmd)
 }
 
 /*
+ * "iface-dumptraffic" command
+ */
+static const vshCmdInfo info_interface_dumptraffic[] = {
+    {"help", N_("dumps traffic on an interface")},
+    {"desc", ""},
+    {NULL, NULL}
+};
+
+static const vshCmdOptDef opts_interface_dumptraffic[] = {
+    {"interface", VSH_OT_DATA, VSH_OFLAG_REQ, N_("interface name")},
+    {"filter", VSH_OT_DATA, 0, N_("packet filter")},
+    {"file", VSH_OT_DATA, 0, N_("file to store packets. If ommited then"
+                                " stdout is used.")},
+    {"snaplen", VSH_OT_INT, 0, N_("capture snaplen. If ommited then the"
+                                  " whole paket is captured")},
+    {"promisc", VSH_OT_BOOL, 0, N_("put the interface into promiscuous mode."
+                                   " Even if not set, the interface could be"
+                                   " in promiscuous mode for some other"
+                                   " reason")},
+    {NULL, 0, 0, NULL}
+};
+
+static bool
+cmdInterfaceDumpTraffic(vshControl *ctl, const vshCmd *cmd)
+{
+    virInterfacePtr iface;
+    const char *iface_name=NULL;
+    virStreamPtr stream = NULL;
+    int fd = STDOUT_FILENO;
+    const char* file = NULL;
+    const char* filter = NULL;
+    bool promisc;
+    unsigned int snaplen=0;
+
+    if (!vshConnectionUsability(ctl, ctl->conn))
+        return false;
+    if (vshCommandOptString(cmd, "filter", &filter) < 0)
+        return false;
+    if (vshCommandOptString(cmd, "file", &file) < 0)
+        return false;
+    if (vshCommandOptUInt(cmd, "snaplen", &snaplen) < 0)
+        return false;
+    promisc = vshCommandOptBool(cmd, "promisc");
+
+    if (!(iface = vshCommandOptInterfaceBy(ctl, cmd, NULL, NULL,
+                                           VSH_BYNAME)))
+        return false;
+    iface_name = virInterfaceGetName(iface);
+
+    stream = virStreamNew(ctl->conn, 0);
+
+    if(virInterfaceDumpTraffic(iface, stream, filter, promisc, snaplen, 0)) {
+        vshError(ctl, _("error virInterfaceDumpTraffic %s"), iface_name);
+        goto cleanup;
+    }
+
+    if (file && (fd = open(file, O_WRONLY|O_CREAT|O_EXCL, 0660)) < 0) {
+        if (errno != EEXIST ||
+            (fd = open(file, O_WRONLY|O_TRUNC, 0660)) < 0) {
+            vshError(ctl, _("cannot create file %s"), file);
+            goto cleanup;
+        }
+    }
+
+    if (virStreamRecvAll(stream, vshStreamSink, &fd) < 0) {
+        vshError(ctl, _("could not receive data from interface %s"), iface_name);
+        goto cleanup;
+    }
+
+    if (virStreamFinish(stream) < 0) {
+        vshError(ctl, _("cannot close stream on interface %s"), iface_name);
+        goto cleanup;
+    }
+
+cleanup:
+    virStreamFree(stream);
+    virInterfaceFree(iface);
+
+    return true;
+}
+
+/*
  * "iface-mac" command
  */
 static const vshCmdInfo info_interface_mac[] = {
@@ -18352,6 +18434,8 @@ static const vshCmdDef ifaceCmds[] = {
      info_interface_define, 0},
     {"iface-destroy", cmdInterfaceDestroy, opts_interface_destroy,
      info_interface_destroy, 0},
+    {"iface-dumptraffic", cmdInterfaceDumpTraffic,
+     opts_interface_dumptraffic, info_interface_dumptraffic, 0},
     {"iface-dumpxml", cmdInterfaceDumpXML, opts_interface_dumpxml,
      info_interface_dumpxml, 0},
     {"iface-edit", cmdInterfaceEdit, opts_interface_edit,
-- 
1.7.9.5




More information about the libvir-list mailing list