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