VirtualBox

source: vbox/trunk/src/VBox/Devices/USB/VUSBSniffer.cpp

Last change on this file was 106061, checked in by vboxsync, 3 months ago

Copyright year updates by scm.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 8.0 KB
Line 
1/* $Id: VUSBSniffer.cpp 106061 2024-09-16 14:03:52Z vboxsync $ */
2/** @file
3 * Virtual USB - Sniffer facility.
4 */
5
6/*
7 * Copyright (C) 2014-2024 Oracle and/or its affiliates.
8 *
9 * This file is part of VirtualBox base platform packages, as
10 * available from https://www.virtualbox.org.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, in version 3 of the
15 * License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <https://www.gnu.org/licenses>.
24 *
25 * SPDX-License-Identifier: GPL-3.0-only
26 */
27
28
29/*********************************************************************************************************************************
30* Header Files *
31*********************************************************************************************************************************/
32#define LOG_GROUP LOG_GROUP_DRV_VUSB
33#include <VBox/log.h>
34#include <iprt/file.h>
35#include <iprt/errcore.h>
36#include <iprt/path.h>
37#include <iprt/mem.h>
38#include <iprt/string.h>
39#include <iprt/semaphore.h>
40#include <iprt/time.h>
41
42#include "VUSBSnifferInternal.h"
43
44
45/*********************************************************************************************************************************
46* Structures and Typedefs *
47*********************************************************************************************************************************/
48
49/**
50 * The internal VUSB sniffer state.
51 */
52typedef struct VUSBSNIFFERINT
53{
54 /** The file handle to dump to. */
55 RTFILE hFile;
56 /** Fast Mutex protecting the state against concurrent access. */
57 RTSEMFASTMUTEX hMtx;
58 /** File stream. */
59 VUSBSNIFFERSTRM Strm;
60 /** Pointer to the used format. */
61 PCVUSBSNIFFERFMT pFmt;
62 /** Format specific state - variable in size. */
63 uint8_t abFmt[1];
64} VUSBSNIFFERINT;
65/** Pointer to the internal VUSB sniffer state. */
66typedef VUSBSNIFFERINT *PVUSBSNIFFERINT;
67
68
69/*********************************************************************************************************************************
70* Static Variables *
71*********************************************************************************************************************************/
72
73static PCVUSBSNIFFERFMT s_aVUsbSnifferFmts[] =
74{
75 &g_VUsbSnifferFmtPcapNg,
76 &g_VUsbSnifferFmtUsbMon,
77 &g_VUsbSnifferFmtVmx,
78};
79
80
81/*********************************************************************************************************************************
82* Internal Functions *
83*********************************************************************************************************************************/
84
85/** @interface_method_impl{VUSBSNIFFERSTRM,pfnWrite} */
86static DECLCALLBACK(int) vusbSnifferStrmWrite(PVUSBSNIFFERSTRM pStrm, const void *pvBuf, size_t cbBuf)
87{
88 PVUSBSNIFFERINT pThis = RT_FROM_MEMBER(pStrm, VUSBSNIFFERINT, Strm);
89
90 return RTFileWrite(pThis->hFile, pvBuf, cbBuf, NULL);
91}
92
93/**
94 * Returns a supporting format writer taken from the given format name.
95 *
96 * @returns Pointer to the format structure or NULL if none was found.
97 * @param pszFmt The format to use.
98 */
99static PCVUSBSNIFFERFMT vusbSnifferGetFmtFromString(const char *pszFmt)
100{
101 for (unsigned i = 0; i < RT_ELEMENTS(s_aVUsbSnifferFmts); i++)
102 {
103 if (!RTStrICmp(pszFmt, s_aVUsbSnifferFmts[i]->szName))
104 return s_aVUsbSnifferFmts[i];
105 }
106
107 return NULL;
108}
109
110/**
111 * Returns a supporting format writer taken from the file suffix.
112 *
113 * @returns Pointer to the format structure or NULL if none was found.
114 * @param pszFilename The file name to take the suffix from.
115 */
116static PCVUSBSNIFFERFMT vusbSnifferGetFmtFromFilename(const char *pszFilename)
117{
118 const char *pszFileExt = RTPathSuffix(pszFilename);
119 if (!pszFileExt)
120 return NULL;
121
122 pszFileExt++; /* Skip the dot. */
123
124 for (unsigned i = 0; i < RT_ELEMENTS(s_aVUsbSnifferFmts); i++)
125 {
126 unsigned idxFileExt = 0;
127
128 while (s_aVUsbSnifferFmts[i]->papszFileExts[idxFileExt])
129 {
130 if (!RTStrICmp(pszFileExt, s_aVUsbSnifferFmts[i]->papszFileExts[idxFileExt]))
131 return s_aVUsbSnifferFmts[i];
132
133 idxFileExt++;
134 }
135 }
136
137 return NULL;
138}
139
140
141DECLHIDDEN(int) VUSBSnifferCreate(PVUSBSNIFFER phSniffer, uint32_t fFlags,
142 const char *pszCaptureFilename, const char *pszFmt,
143 const char *pszDesc)
144{
145 RT_NOREF(pszDesc);
146 int rc = VINF_SUCCESS;
147 PVUSBSNIFFERINT pThis = NULL;
148 PCVUSBSNIFFERFMT pFmt = NULL;
149
150 if (pszFmt)
151 pFmt = vusbSnifferGetFmtFromString(pszFmt);
152 else
153 pFmt = vusbSnifferGetFmtFromFilename(pszCaptureFilename);
154
155 if (!pFmt)
156 return VERR_NOT_FOUND;
157
158 pThis = (PVUSBSNIFFERINT)RTMemAllocZ(RT_UOFFSETOF_DYN(VUSBSNIFFERINT, abFmt[pFmt->cbFmt]));
159 if (pThis)
160 {
161 pThis->hFile = NIL_RTFILE;
162 pThis->hMtx = NIL_RTSEMFASTMUTEX;
163 pThis->pFmt = pFmt;
164 pThis->Strm.pfnWrite = vusbSnifferStrmWrite;
165
166 rc = RTSemFastMutexCreate(&pThis->hMtx);
167 if (RT_SUCCESS(rc))
168 {
169 uint32_t fFileFlags = RTFILE_O_DENY_NONE | RTFILE_O_WRITE | RTFILE_O_READ;
170 if (fFlags & VUSBSNIFFER_F_NO_REPLACE)
171 fFileFlags |= RTFILE_O_CREATE;
172 else
173 fFileFlags |= RTFILE_O_CREATE_REPLACE;
174
175 rc = RTFileOpen(&pThis->hFile, pszCaptureFilename, fFileFlags);
176 if (RT_SUCCESS(rc))
177 {
178 rc = pThis->pFmt->pfnInit((PVUSBSNIFFERFMTINT)&pThis->abFmt[0], &pThis->Strm);
179 if (RT_SUCCESS(rc))
180 {
181 *phSniffer = pThis;
182 return VINF_SUCCESS;
183 }
184
185 RTFileClose(pThis->hFile);
186 pThis->hFile = NIL_RTFILE;
187 RTFileDelete(pszCaptureFilename);
188 }
189 RTSemFastMutexDestroy(pThis->hMtx);
190 pThis->hMtx = NIL_RTSEMFASTMUTEX;
191 }
192
193 RTMemFree(pThis);
194 }
195 else
196 rc = VERR_NO_MEMORY;
197
198 return rc;
199}
200
201/**
202 * Destroys the given VUSB sniffer instance.
203 *
204 * @param hSniffer The sniffer instance to destroy.
205 */
206DECLHIDDEN(void) VUSBSnifferDestroy(VUSBSNIFFER hSniffer)
207{
208 PVUSBSNIFFERINT pThis = hSniffer;
209
210 int rc = RTSemFastMutexRequest(pThis->hMtx);
211 AssertRC(rc);
212
213 pThis->pFmt->pfnDestroy((PVUSBSNIFFERFMTINT)&pThis->abFmt[0]);
214
215 if (pThis->hFile != NIL_RTFILE)
216 RTFileClose(pThis->hFile);
217
218 RTSemFastMutexRelease(pThis->hMtx);
219 RTSemFastMutexDestroy(pThis->hMtx);
220 RTMemFree(pThis);
221}
222
223/**
224 * Records an VUSB event.
225 *
226 * @returns VBox status code.
227 * @param hSniffer The sniffer instance.
228 * @param pUrb The URB triggering the event.
229 * @param enmEvent The type of event to record.
230 */
231DECLHIDDEN(int) VUSBSnifferRecordEvent(VUSBSNIFFER hSniffer, PVUSBURB pUrb, VUSBSNIFFEREVENT enmEvent)
232{
233 int rc = VINF_SUCCESS;
234 PVUSBSNIFFERINT pThis = hSniffer;
235
236 /* Write the packet to the capture file. */
237 rc = RTSemFastMutexRequest(pThis->hMtx);
238 if (RT_SUCCESS(rc))
239 {
240 rc = pThis->pFmt->pfnRecordEvent((PVUSBSNIFFERFMTINT)&pThis->abFmt[0], pUrb, enmEvent);
241 RTSemFastMutexRelease(pThis->hMtx);
242 }
243
244 return rc;
245}
246
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette