From f215e02bf85f68d3a6106c2a1f4f7f063f819064 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Thu, 11 Apr 2024 10:17:27 +0200 Subject: Adding upstream version 7.0.14-dfsg. Signed-off-by: Daniel Baumann --- src/VBox/Frontends/VBoxIntnetPcap/Makefile.kmk | 46 ++++ .../Frontends/VBoxIntnetPcap/VBoxIntnetPcap.cpp | 233 +++++++++++++++++++++ 2 files changed, 279 insertions(+) create mode 100644 src/VBox/Frontends/VBoxIntnetPcap/Makefile.kmk create mode 100644 src/VBox/Frontends/VBoxIntnetPcap/VBoxIntnetPcap.cpp (limited to 'src/VBox/Frontends/VBoxIntnetPcap') diff --git a/src/VBox/Frontends/VBoxIntnetPcap/Makefile.kmk b/src/VBox/Frontends/VBoxIntnetPcap/Makefile.kmk new file mode 100644 index 00000000..627068b5 --- /dev/null +++ b/src/VBox/Frontends/VBoxIntnetPcap/Makefile.kmk @@ -0,0 +1,46 @@ +# $Id: Makefile.kmk $ +## @file +# Sub-makefile for the VBoxIntnetPcap +# + +# +# Copyright (C) 2021-2023 Oracle and/or its affiliates. +# +# This file is part of VirtualBox base platform packages, as +# available from https://www.virtualbox.org. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation, in version 3 of the +# License. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, see . +# +# SPDX-License-Identifier: GPL-3.0-only +# + +SUB_DEPTH = ../../../.. +include $(KBUILD_PATH)/subheader.kmk + +PROGRAMS += VBoxIntnetPcap +VBoxIntnetPcap_TEMPLATE := VBoxR3Exe +VBoxIntnetPcap_DEFS := \ + $(if $(VBOX_WITH_INTNET_SERVICE_IN_R3),VBOX_WITH_INTNET_SERVICE_IN_R3,) +VBoxIntnetPcap_INCS := \ + ../../NetworkServices/NetLib \ + ../../Devices/Network +VBoxIntnetPcap_SOURCES := \ + VBoxIntnetPcap.cpp \ + ../../NetworkServices/NetLib/IntNetIf.cpp \ + ../../Devices/Network/Pcap.cpp +VBoxIntnetPcap_LIBS = $(LIB_RUNTIME) +# VBoxIntnetPcap_LIBS.solaris += socket nsl # XXX: when we add rpcapd support + +include $(FILE_KBUILD_SUB_FOOTER) + diff --git a/src/VBox/Frontends/VBoxIntnetPcap/VBoxIntnetPcap.cpp b/src/VBox/Frontends/VBoxIntnetPcap/VBoxIntnetPcap.cpp new file mode 100644 index 00000000..ae45acf5 --- /dev/null +++ b/src/VBox/Frontends/VBoxIntnetPcap/VBoxIntnetPcap.cpp @@ -0,0 +1,233 @@ +/* $Id: VBoxIntnetPcap.cpp $ */ +/** @file + * VBoxIntnetPcap - packet capture for VirtualBox internal networks + */ + +/* + * Copyright (C) 2021-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + * + * SPDX-License-Identifier: GPL-3.0-only + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include "IntNetIf.h" +#include "Pcap.h" + +#include +#include +#include +#include +#include +#include + +#include + +#include + + +/********************************************************************************************************************************* +* Internal Functions * +*********************************************************************************************************************************/ + + +/********************************************************************************************************************************* +* Global Variables * +*********************************************************************************************************************************/ +static INTNETIFCTX g_hIntNetCtx; +static PRTSTREAM g_pStrmOut; +static uint64_t g_StartNanoTS; +static bool g_fPacketBuffered; +static uint64_t g_cCountDown; +static size_t g_cbSnapLen = 0xffff; + +static const RTGETOPTDEF g_aGetOptDef[] = +{ + { "--count", 'c', RTGETOPT_REQ_UINT64 }, + { "--network", 'i', RTGETOPT_REQ_STRING }, + { "--snaplen", 's', RTGETOPT_REQ_UINT32 }, + { "--packet-buffered", 'U', RTGETOPT_REQ_NOTHING }, + { "--write", 'w', RTGETOPT_REQ_STRING }, +}; + + +static void checkCaptureLimit(void) +{ + if (g_cCountDown > 0) + { + if (g_cCountDown-- == 1) + IntNetR3IfWaitAbort(g_hIntNetCtx); + } +} + + +static DECLCALLBACK(void) captureFrame(void *pvUser, void *pvFrame, uint32_t cbFrame) +{ + RT_NOREF(pvUser); + + int rc = PcapStreamFrame(g_pStrmOut, g_StartNanoTS, pvFrame, cbFrame, g_cbSnapLen); + if (RT_FAILURE(rc)) + { + RTMsgError("write: %Rrf", rc); + IntNetR3IfWaitAbort(g_hIntNetCtx); + } + + if (g_fPacketBuffered) + RTStrmFlush(g_pStrmOut); + + checkCaptureLimit(); +} + + +static DECLCALLBACK(void) captureGSO(void *pvUser, PCPDMNETWORKGSO pcGso, uint32_t cbFrame) +{ + RT_NOREF(pvUser, pcGso, cbFrame); + + checkCaptureLimit(); +} + + +int +main(int argc, char *argv[]) +{ + int rc = RTR3InitExe(argc, &argv, RTR3INIT_FLAGS_SUPLIB); + if (RT_FAILURE(rc)) + return RTMsgInitFailure(rc); + + /* + * Parse options + */ + RTGETOPTSTATE State; + rc = RTGetOptInit(&State, argc, argv, g_aGetOptDef, RT_ELEMENTS(g_aGetOptDef), 1, 0); + AssertRC(rc); + + const char *pszNetworkName = NULL; + const char *pszPcapFile = NULL; + + int ch; + RTGETOPTUNION Val; + while ((ch = RTGetOpt(&State, &Val)) != 0) + { + switch (ch) + { + case 'c': /* --count */ + if (Val.u64 == 0) + return RTMsgErrorExit(RTEXITCODE_SYNTAX, "--count must be greater than zero"); + g_cCountDown = Val.u64; + break; + + case 'i': /* --network */ + if (Val.psz[0] == '\0') + return RTMsgErrorExit(RTEXITCODE_SYNTAX, "empty --network option"); + pszNetworkName = Val.psz; + break; + + case 's': /* --snaplen */ + if (Val.u32 == 0) + return RTMsgErrorExit(RTEXITCODE_SYNTAX, "--snaplen must be greater than zero"); + g_cbSnapLen = Val.u32; + break; + + case 'U': /* --packet-buffered */ + g_fPacketBuffered = true; + break; + + case 'w': /* --write */ + if (Val.psz[0] == '\0') + return RTMsgErrorExit(RTEXITCODE_SYNTAX, "empty --write option"); + pszPcapFile = Val.psz; + break; + + + /* + * Standard options recognized by RTGetOpt() + */ + case 'V': /* --version */ + RTPrintf("%sr%u\n", RTBldCfgVersion(), RTBldCfgRevision()); + return RTEXITCODE_SUCCESS; + + case 'h': /* --help */ + RTPrintf("%s Version %sr%u\n" + "Copyright (C) 2009-" VBOX_C_YEAR " " VBOX_VENDOR "\n" + "\n" + "Usage: %s \n" + "\n" + "Options:\n", + RTProcShortName(), RTBldCfgVersion(), RTBldCfgRevision(), + RTProcShortName()); + for (size_t i = 0; i < RT_ELEMENTS(g_aGetOptDef); ++i) + RTPrintf(" -%c, %s\n", + g_aGetOptDef[i].iShort, g_aGetOptDef[i].pszLong); + return RTEXITCODE_SUCCESS; + + default: + case VINF_GETOPT_NOT_OPTION: + return RTGetOptPrintError(ch, &Val); + } + } + if (!pszNetworkName) + return RTMsgErrorExit(RTEXITCODE_SYNTAX, "No network specified. Please use the --network option"); + if (!pszPcapFile) + return RTMsgErrorExit(RTEXITCODE_SYNTAX, "No output file specified. Please use the --write option"); + + /* + * Open the output file. + */ + if (strcmp(pszPcapFile, "-") == 0) + g_pStrmOut = g_pStdOut; + else + { + rc = RTStrmOpen(pszPcapFile, "wb", &g_pStrmOut); + if (RT_FAILURE(rc)) + return RTMsgErrorExitFailure("%s: %Rrf", pszPcapFile, rc); + } + + rc = IntNetR3IfCreate(&g_hIntNetCtx, pszNetworkName); + if (RT_FAILURE(rc)) + return RTMsgErrorExitFailure("Opening the internal network '%s' failed with %Rrc\n", pszNetworkName, rc); + + rc = IntNetR3IfSetPromiscuous(g_hIntNetCtx, true /*fPromiscuous*/); + if (RT_FAILURE(rc)) + return RTMsgErrorExitFailure("Enabling promiscuous mode on the internal network '%s' failed with %Rrc\n", pszNetworkName, rc); + + rc = IntNetR3IfSetActive(g_hIntNetCtx, true /*fActive*/); + if (RT_FAILURE(rc)) + return RTMsgErrorExitFailure("Activating interface on the internal network '%s' failed with %Rrc\n", pszNetworkName, rc); + + /* + * Snoop traffic. + */ + g_StartNanoTS = RTTimeNanoTS(); + rc = PcapStreamHdr(g_pStrmOut, g_StartNanoTS); + if (RT_FAILURE(rc)) + return RTMsgErrorExitFailure("write: %Rrf", rc); + if (g_fPacketBuffered) + RTStrmFlush(g_pStrmOut); + + rc = IntNetR3IfPumpPkts(g_hIntNetCtx, captureFrame, NULL /*pvUser*/, + captureGSO, NULL /*pvUserGso*/); + + RTEXITCODE rcExit = RT_SUCCESS(RTStrmError(g_pStrmOut)) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE; + rc = RTStrmClose(g_pStrmOut); + if (RT_FAILURE(rc)) + rcExit = RTMsgErrorExitFailure("close: %Rrf", rc); + return rcExit; +} -- cgit v1.2.3