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