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/Devices/USB/VUSBSniffer.cpp | 246 +++++++++++++++++++++++++++++++++++ 1 file changed, 246 insertions(+) create mode 100644 src/VBox/Devices/USB/VUSBSniffer.cpp (limited to 'src/VBox/Devices/USB/VUSBSniffer.cpp') diff --git a/src/VBox/Devices/USB/VUSBSniffer.cpp b/src/VBox/Devices/USB/VUSBSniffer.cpp new file mode 100644 index 00000000..a17ef89e --- /dev/null +++ b/src/VBox/Devices/USB/VUSBSniffer.cpp @@ -0,0 +1,246 @@ +/* $Id: VUSBSniffer.cpp $ */ +/** @file + * Virtual USB - Sniffer facility. + */ + +/* + * Copyright (C) 2014-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 * +*********************************************************************************************************************************/ +#define LOG_GROUP LOG_GROUP_DRV_VUSB +#include +#include +#include +#include +#include +#include +#include +#include + +#include "VUSBSnifferInternal.h" + + +/********************************************************************************************************************************* +* Structures and Typedefs * +*********************************************************************************************************************************/ + +/** + * The internal VUSB sniffer state. + */ +typedef struct VUSBSNIFFERINT +{ + /** The file handle to dump to. */ + RTFILE hFile; + /** Fast Mutex protecting the state against concurrent access. */ + RTSEMFASTMUTEX hMtx; + /** File stream. */ + VUSBSNIFFERSTRM Strm; + /** Pointer to the used format. */ + PCVUSBSNIFFERFMT pFmt; + /** Format specific state - variable in size. */ + uint8_t abFmt[1]; +} VUSBSNIFFERINT; +/** Pointer to the internal VUSB sniffer state. */ +typedef VUSBSNIFFERINT *PVUSBSNIFFERINT; + + +/********************************************************************************************************************************* +* Static Variables * +*********************************************************************************************************************************/ + +static PCVUSBSNIFFERFMT s_aVUsbSnifferFmts[] = +{ + &g_VUsbSnifferFmtPcapNg, + &g_VUsbSnifferFmtUsbMon, + &g_VUsbSnifferFmtVmx, +}; + + +/********************************************************************************************************************************* +* Internal Functions * +*********************************************************************************************************************************/ + +/** @interface_method_impl{VUSBSNIFFERSTRM,pfnWrite} */ +static DECLCALLBACK(int) vusbSnifferStrmWrite(PVUSBSNIFFERSTRM pStrm, const void *pvBuf, size_t cbBuf) +{ + PVUSBSNIFFERINT pThis = RT_FROM_MEMBER(pStrm, VUSBSNIFFERINT, Strm); + + return RTFileWrite(pThis->hFile, pvBuf, cbBuf, NULL); +} + +/** + * Returns a supporting format writer taken from the given format name. + * + * @returns Pointer to the format structure or NULL if none was found. + * @param pszFmt The format to use. + */ +static PCVUSBSNIFFERFMT vusbSnifferGetFmtFromString(const char *pszFmt) +{ + for (unsigned i = 0; i < RT_ELEMENTS(s_aVUsbSnifferFmts); i++) + { + if (!RTStrICmp(pszFmt, s_aVUsbSnifferFmts[i]->szName)) + return s_aVUsbSnifferFmts[i]; + } + + return NULL; +} + +/** + * Returns a supporting format writer taken from the file suffix. + * + * @returns Pointer to the format structure or NULL if none was found. + * @param pszFilename The file name to take the suffix from. + */ +static PCVUSBSNIFFERFMT vusbSnifferGetFmtFromFilename(const char *pszFilename) +{ + const char *pszFileExt = RTPathSuffix(pszFilename); + if (!pszFileExt) + return NULL; + + pszFileExt++; /* Skip the dot. */ + + for (unsigned i = 0; i < RT_ELEMENTS(s_aVUsbSnifferFmts); i++) + { + unsigned idxFileExt = 0; + + while (s_aVUsbSnifferFmts[i]->papszFileExts[idxFileExt]) + { + if (!RTStrICmp(pszFileExt, s_aVUsbSnifferFmts[i]->papszFileExts[idxFileExt])) + return s_aVUsbSnifferFmts[i]; + + idxFileExt++; + } + } + + return NULL; +} + + +DECLHIDDEN(int) VUSBSnifferCreate(PVUSBSNIFFER phSniffer, uint32_t fFlags, + const char *pszCaptureFilename, const char *pszFmt, + const char *pszDesc) +{ + RT_NOREF(pszDesc); + int rc = VINF_SUCCESS; + PVUSBSNIFFERINT pThis = NULL; + PCVUSBSNIFFERFMT pFmt = NULL; + + if (pszFmt) + pFmt = vusbSnifferGetFmtFromString(pszFmt); + else + pFmt = vusbSnifferGetFmtFromFilename(pszCaptureFilename); + + if (!pFmt) + return VERR_NOT_FOUND; + + pThis = (PVUSBSNIFFERINT)RTMemAllocZ(RT_UOFFSETOF_DYN(VUSBSNIFFERINT, abFmt[pFmt->cbFmt])); + if (pThis) + { + pThis->hFile = NIL_RTFILE; + pThis->hMtx = NIL_RTSEMFASTMUTEX; + pThis->pFmt = pFmt; + pThis->Strm.pfnWrite = vusbSnifferStrmWrite; + + rc = RTSemFastMutexCreate(&pThis->hMtx); + if (RT_SUCCESS(rc)) + { + uint32_t fFileFlags = RTFILE_O_DENY_NONE | RTFILE_O_WRITE | RTFILE_O_READ; + if (fFlags & VUSBSNIFFER_F_NO_REPLACE) + fFileFlags |= RTFILE_O_CREATE; + else + fFileFlags |= RTFILE_O_CREATE_REPLACE; + + rc = RTFileOpen(&pThis->hFile, pszCaptureFilename, fFileFlags); + if (RT_SUCCESS(rc)) + { + rc = pThis->pFmt->pfnInit((PVUSBSNIFFERFMTINT)&pThis->abFmt[0], &pThis->Strm); + if (RT_SUCCESS(rc)) + { + *phSniffer = pThis; + return VINF_SUCCESS; + } + + RTFileClose(pThis->hFile); + pThis->hFile = NIL_RTFILE; + RTFileDelete(pszCaptureFilename); + } + RTSemFastMutexDestroy(pThis->hMtx); + pThis->hMtx = NIL_RTSEMFASTMUTEX; + } + + RTMemFree(pThis); + } + else + rc = VERR_NO_MEMORY; + + return rc; +} + +/** + * Destroys the given VUSB sniffer instance. + * + * @param hSniffer The sniffer instance to destroy. + */ +DECLHIDDEN(void) VUSBSnifferDestroy(VUSBSNIFFER hSniffer) +{ + PVUSBSNIFFERINT pThis = hSniffer; + + int rc = RTSemFastMutexRequest(pThis->hMtx); + AssertRC(rc); + + pThis->pFmt->pfnDestroy((PVUSBSNIFFERFMTINT)&pThis->abFmt[0]); + + if (pThis->hFile != NIL_RTFILE) + RTFileClose(pThis->hFile); + + RTSemFastMutexRelease(pThis->hMtx); + RTSemFastMutexDestroy(pThis->hMtx); + RTMemFree(pThis); +} + +/** + * Records an VUSB event. + * + * @returns VBox status code. + * @param hSniffer The sniffer instance. + * @param pUrb The URB triggering the event. + * @param enmEvent The type of event to record. + */ +DECLHIDDEN(int) VUSBSnifferRecordEvent(VUSBSNIFFER hSniffer, PVUSBURB pUrb, VUSBSNIFFEREVENT enmEvent) +{ + int rc = VINF_SUCCESS; + PVUSBSNIFFERINT pThis = hSniffer; + + /* Write the packet to the capture file. */ + rc = RTSemFastMutexRequest(pThis->hMtx); + if (RT_SUCCESS(rc)) + { + rc = pThis->pFmt->pfnRecordEvent((PVUSBSNIFFERFMTINT)&pThis->abFmt[0], pUrb, enmEvent); + RTSemFastMutexRelease(pThis->hMtx); + } + + return rc; +} + -- cgit v1.2.3