VirtualBox

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

Last change on this file since 95274 was 93115, checked in by vboxsync, 3 years ago

scm --update-copyright-year

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