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 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list