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

Hendrik Schwartke hendrik at os-t.de
Thu Jul 26 11:15:10 UTC 2012


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

diff --git a/tools/virsh.c b/tools/virsh.c
index 1e00049..5ccec39 100644
--- a/tools/virsh.c
+++ b/tools/virsh.c
@@ -9253,6 +9253,91 @@ cmdInterfaceName(vshControl *ctl, const vshCmd *cmd)
 }
 
 /*
+ * "iface-capture" command
+ */
+static const vshCmdInfo info_interface_capture[] = {
+    {"help", N_("captures traffic on an interface")},
+    {"desc", ""},
+    {NULL, NULL}
+};
+
+static const vshCmdOptDef opts_interface_capture[] = {
+    {"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
+cmdInterfaceCapture(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;
+    int flags = 0;
+    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;
+    if(vshCommandOptBool(cmd, "promisc"))
+        flags |= VIR_NET_DEV_CAPTURE_PROMISC;
+
+    if (!(iface = vshCommandOptInterfaceBy(ctl, cmd, NULL, NULL,
+                                           VSH_BYNAME)))
+        return false;
+    iface_name = virInterfaceGetName(iface);
+
+     
+
+    stream = virStreamNew(ctl->conn, 0);
+
+    if(virInterfaceCapture(iface, stream, filter, snaplen, flags)) {
+        vshError(ctl, _("error virInterfaceCapture %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[] = {
@@ -18346,6 +18431,8 @@ static const vshCmdDef ifaceCmds[] = {
      info_interface_begin, 0},
     {"iface-bridge", cmdInterfaceBridge, opts_interface_bridge,
      info_interface_bridge, 0},
+    {"iface-capture", cmdInterfaceCapture, opts_interface_capture,
+     info_interface_capture, 0},
     {"iface-commit", cmdInterfaceCommit, opts_interface_commit,
      info_interface_commit, 0},
     {"iface-define", cmdInterfaceDefine, opts_interface_define,
-- 
1.7.9.5




More information about the libvir-list mailing list