VirtualBox

source: vbox/trunk/src/VBox/Devices/Network/DrvNetSniffer.cpp

Last change on this file was 98103, checked in by vboxsync, 16 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: 18.9 KB
Line 
1/* $Id: DrvNetSniffer.cpp 98103 2023-01-17 14:15:46Z vboxsync $ */
2/** @file
3 * DrvNetSniffer - Network sniffer filter driver.
4 */
5
6/*
7 * Copyright (C) 2006-2023 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_NAT
33#include <VBox/vmm/pdmdrv.h>
34#include <VBox/vmm/pdmnetifs.h>
35
36#include <VBox/log.h>
37#include <iprt/assert.h>
38#include <iprt/critsect.h>
39#include <iprt/file.h>
40#include <iprt/process.h>
41#include <iprt/string.h>
42#include <iprt/time.h>
43#include <iprt/uuid.h>
44#include <iprt/path.h>
45#include <VBox/param.h>
46
47#include "Pcap.h"
48#include "VBoxDD.h"
49
50
51/*********************************************************************************************************************************
52* Structures and Typedefs *
53*********************************************************************************************************************************/
54/**
55 * Block driver instance data.
56 *
57 * @implements PDMINETWORKUP
58 * @implements PDMINETWORKDOWN
59 * @implements PDMINETWORKCONFIG
60 */
61typedef struct DRVNETSNIFFER
62{
63 /** The network interface. */
64 PDMINETWORKUP INetworkUp;
65 /** The network interface. */
66 PDMINETWORKDOWN INetworkDown;
67 /** The network config interface.
68 * @todo this is a main interface and shouldn't be here... */
69 PDMINETWORKCONFIG INetworkConfig;
70 /** The port we're attached to. */
71 PPDMINETWORKDOWN pIAboveNet;
72 /** The config port interface we're attached to. */
73 PPDMINETWORKCONFIG pIAboveConfig;
74 /** The connector that's attached to us. */
75 PPDMINETWORKUP pIBelowNet;
76 /** The filename. */
77 char szFilename[RTPATH_MAX];
78 /** The filehandle. */
79 RTFILE hFile;
80 /** The lock serializing the file access. */
81 RTCRITSECT Lock;
82 /** The NanoTS delta we pass to the pcap writers. */
83 uint64_t StartNanoTS;
84 /** Pointer to the driver instance. */
85 PPDMDRVINS pDrvIns;
86 /** For when we're the leaf driver. */
87 RTCRITSECT XmitLock;
88
89} DRVNETSNIFFER, *PDRVNETSNIFFER;
90
91
92
93/**
94 * @interface_method_impl{PDMINETWORKUP,pfnBeginXmit}
95 */
96static DECLCALLBACK(int) drvNetSnifferUp_BeginXmit(PPDMINETWORKUP pInterface, bool fOnWorkerThread)
97{
98 PDRVNETSNIFFER pThis = RT_FROM_MEMBER(pInterface, DRVNETSNIFFER, INetworkUp);
99 if (RT_UNLIKELY(!pThis->pIBelowNet))
100 {
101 int rc = RTCritSectTryEnter(&pThis->XmitLock);
102 if (RT_UNLIKELY(rc == VERR_SEM_BUSY))
103 rc = VERR_TRY_AGAIN;
104 return rc;
105 }
106 return pThis->pIBelowNet->pfnBeginXmit(pThis->pIBelowNet, fOnWorkerThread);
107}
108
109
110/**
111 * @interface_method_impl{PDMINETWORKUP,pfnAllocBuf}
112 */
113static DECLCALLBACK(int) drvNetSnifferUp_AllocBuf(PPDMINETWORKUP pInterface, size_t cbMin,
114 PCPDMNETWORKGSO pGso, PPPDMSCATTERGATHER ppSgBuf)
115{
116 PDRVNETSNIFFER pThis = RT_FROM_MEMBER(pInterface, DRVNETSNIFFER, INetworkUp);
117 if (RT_UNLIKELY(!pThis->pIBelowNet))
118 return VERR_NET_DOWN;
119 return pThis->pIBelowNet->pfnAllocBuf(pThis->pIBelowNet, cbMin, pGso, ppSgBuf);
120}
121
122
123/**
124 * @interface_method_impl{PDMINETWORKUP,pfnFreeBuf}
125 */
126static DECLCALLBACK(int) drvNetSnifferUp_FreeBuf(PPDMINETWORKUP pInterface, PPDMSCATTERGATHER pSgBuf)
127{
128 PDRVNETSNIFFER pThis = RT_FROM_MEMBER(pInterface, DRVNETSNIFFER, INetworkUp);
129 if (RT_UNLIKELY(!pThis->pIBelowNet))
130 return VERR_NET_DOWN;
131 return pThis->pIBelowNet->pfnFreeBuf(pThis->pIBelowNet, pSgBuf);
132}
133
134
135/**
136 * @interface_method_impl{PDMINETWORKUP,pfnSendBuf}
137 */
138static DECLCALLBACK(int) drvNetSnifferUp_SendBuf(PPDMINETWORKUP pInterface, PPDMSCATTERGATHER pSgBuf, bool fOnWorkerThread)
139{
140 PDRVNETSNIFFER pThis = RT_FROM_MEMBER(pInterface, DRVNETSNIFFER, INetworkUp);
141 if (RT_UNLIKELY(!pThis->pIBelowNet))
142 return VERR_NET_DOWN;
143
144 /* output to sniffer */
145 RTCritSectEnter(&pThis->Lock);
146 if (!pSgBuf->pvUser)
147 PcapFileFrame(pThis->hFile, pThis->StartNanoTS,
148 pSgBuf->aSegs[0].pvSeg,
149 pSgBuf->cbUsed,
150 RT_MIN(pSgBuf->cbUsed, pSgBuf->aSegs[0].cbSeg));
151 else
152 PcapFileGsoFrame(pThis->hFile, pThis->StartNanoTS, (PCPDMNETWORKGSO)pSgBuf->pvUser,
153 pSgBuf->aSegs[0].pvSeg,
154 pSgBuf->cbUsed,
155 RT_MIN(pSgBuf->cbUsed, pSgBuf->aSegs[0].cbSeg));
156 RTCritSectLeave(&pThis->Lock);
157
158 return pThis->pIBelowNet->pfnSendBuf(pThis->pIBelowNet, pSgBuf, fOnWorkerThread);
159}
160
161
162/**
163 * @interface_method_impl{PDMINETWORKUP,pfnEndXmit}
164 */
165static DECLCALLBACK(void) drvNetSnifferUp_EndXmit(PPDMINETWORKUP pInterface)
166{
167 LogFlow(("drvNetSnifferUp_EndXmit:\n"));
168 PDRVNETSNIFFER pThis = RT_FROM_MEMBER(pInterface, DRVNETSNIFFER, INetworkUp);
169 if (RT_LIKELY(pThis->pIBelowNet))
170 pThis->pIBelowNet->pfnEndXmit(pThis->pIBelowNet);
171 else
172 RTCritSectLeave(&pThis->XmitLock);
173}
174
175
176/**
177 * @interface_method_impl{PDMINETWORKUP,pfnSetPromiscuousMode}
178 */
179static DECLCALLBACK(void) drvNetSnifferUp_SetPromiscuousMode(PPDMINETWORKUP pInterface, bool fPromiscuous)
180{
181 LogFlow(("drvNetSnifferUp_SetPromiscuousMode: fPromiscuous=%d\n", fPromiscuous));
182 PDRVNETSNIFFER pThis = RT_FROM_MEMBER(pInterface, DRVNETSNIFFER, INetworkUp);
183 if (pThis->pIBelowNet)
184 pThis->pIBelowNet->pfnSetPromiscuousMode(pThis->pIBelowNet, fPromiscuous);
185}
186
187
188/**
189 * @interface_method_impl{PDMINETWORKUP,pfnNotifyLinkChanged}
190 */
191static DECLCALLBACK(void) drvNetSnifferUp_NotifyLinkChanged(PPDMINETWORKUP pInterface, PDMNETWORKLINKSTATE enmLinkState)
192{
193 LogFlow(("drvNetSnifferUp_NotifyLinkChanged: enmLinkState=%d\n", enmLinkState));
194 PDRVNETSNIFFER pThis = RT_FROM_MEMBER(pInterface, DRVNETSNIFFER, INetworkUp);
195 if (pThis->pIBelowNet)
196 pThis->pIBelowNet->pfnNotifyLinkChanged(pThis->pIBelowNet, enmLinkState);
197}
198
199
200/**
201 * @interface_method_impl{PDMINETWORKDOWN,pfnWaitReceiveAvail}
202 */
203static DECLCALLBACK(int) drvNetSnifferDown_WaitReceiveAvail(PPDMINETWORKDOWN pInterface, RTMSINTERVAL cMillies)
204{
205 PDRVNETSNIFFER pThis = RT_FROM_MEMBER(pInterface, DRVNETSNIFFER, INetworkDown);
206 return pThis->pIAboveNet->pfnWaitReceiveAvail(pThis->pIAboveNet, cMillies);
207}
208
209
210/**
211 * @interface_method_impl{PDMINETWORKDOWN,pfnReceive}
212 */
213static DECLCALLBACK(int) drvNetSnifferDown_Receive(PPDMINETWORKDOWN pInterface, const void *pvBuf, size_t cb)
214{
215 PDRVNETSNIFFER pThis = RT_FROM_MEMBER(pInterface, DRVNETSNIFFER, INetworkDown);
216
217 /* output to sniffer */
218 RTCritSectEnter(&pThis->Lock);
219 PcapFileFrame(pThis->hFile, pThis->StartNanoTS, pvBuf, cb, cb);
220 RTCritSectLeave(&pThis->Lock);
221
222 /* pass up */
223 int rc = pThis->pIAboveNet->pfnReceive(pThis->pIAboveNet, pvBuf, cb);
224#if 0
225 RTCritSectEnter(&pThis->Lock);
226 u64TS = RTTimeProgramNanoTS();
227 Hdr.ts_sec = (uint32_t)(u64TS / 1000000000);
228 Hdr.ts_usec = (uint32_t)((u64TS / 1000) % 1000000);
229 Hdr.incl_len = 0;
230 RTFileWrite(pThis->hFile, &Hdr, sizeof(Hdr), NULL);
231 RTCritSectLeave(&pThis->Lock);
232#endif
233 return rc;
234}
235
236
237/**
238 * @interface_method_impl{PDMINETWORKDOWN,pfnXmitPending}
239 */
240static DECLCALLBACK(void) drvNetSnifferDown_XmitPending(PPDMINETWORKDOWN pInterface)
241{
242 PDRVNETSNIFFER pThis = RT_FROM_MEMBER(pInterface, DRVNETSNIFFER, INetworkDown);
243 pThis->pIAboveNet->pfnXmitPending(pThis->pIAboveNet);
244}
245
246
247/**
248 * Gets the current Media Access Control (MAC) address.
249 *
250 * @returns VBox status code.
251 * @param pInterface Pointer to the interface structure containing the called function pointer.
252 * @param pMac Where to store the MAC address.
253 * @thread EMT
254 */
255static DECLCALLBACK(int) drvNetSnifferDownCfg_GetMac(PPDMINETWORKCONFIG pInterface, PRTMAC pMac)
256{
257 PDRVNETSNIFFER pThis = RT_FROM_MEMBER(pInterface, DRVNETSNIFFER, INetworkConfig);
258 return pThis->pIAboveConfig->pfnGetMac(pThis->pIAboveConfig, pMac);
259}
260
261/**
262 * Gets the new link state.
263 *
264 * @returns The current link state.
265 * @param pInterface Pointer to the interface structure containing the called function pointer.
266 * @thread EMT
267 */
268static DECLCALLBACK(PDMNETWORKLINKSTATE) drvNetSnifferDownCfg_GetLinkState(PPDMINETWORKCONFIG pInterface)
269{
270 PDRVNETSNIFFER pThis = RT_FROM_MEMBER(pInterface, DRVNETSNIFFER, INetworkConfig);
271 return pThis->pIAboveConfig->pfnGetLinkState(pThis->pIAboveConfig);
272}
273
274/**
275 * Sets the new link state.
276 *
277 * @returns VBox status code.
278 * @param pInterface Pointer to the interface structure containing the called function pointer.
279 * @param enmState The new link state
280 * @thread EMT
281 */
282static DECLCALLBACK(int) drvNetSnifferDownCfg_SetLinkState(PPDMINETWORKCONFIG pInterface, PDMNETWORKLINKSTATE enmState)
283{
284 PDRVNETSNIFFER pThis = RT_FROM_MEMBER(pInterface, DRVNETSNIFFER, INetworkConfig);
285 return pThis->pIAboveConfig->pfnSetLinkState(pThis->pIAboveConfig, enmState);
286}
287
288
289/**
290 * @interface_method_impl{PDMIBASE,pfnQueryInterface}
291 */
292static DECLCALLBACK(void *) drvNetSnifferQueryInterface(PPDMIBASE pInterface, const char *pszIID)
293{
294 PPDMDRVINS pDrvIns = PDMIBASE_2_PDMDRV(pInterface);
295 PDRVNETSNIFFER pThis = PDMINS_2_DATA(pDrvIns, PDRVNETSNIFFER);
296 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pDrvIns->IBase);
297 PDMIBASE_RETURN_INTERFACE(pszIID, PDMINETWORKUP, &pThis->INetworkUp);
298 PDMIBASE_RETURN_INTERFACE(pszIID, PDMINETWORKDOWN, &pThis->INetworkDown);
299 PDMIBASE_RETURN_INTERFACE(pszIID, PDMINETWORKCONFIG, &pThis->INetworkConfig);
300 return NULL;
301}
302
303
304/**
305 * @interface_method_impl{PDMDRVREG,pfnDetach}
306 */
307static DECLCALLBACK(void) drvNetSnifferDetach(PPDMDRVINS pDrvIns, uint32_t fFlags)
308{
309 RT_NOREF(fFlags);
310 PDRVNETSNIFFER pThis = PDMINS_2_DATA(pDrvIns, PDRVNETSNIFFER);
311
312 LogFlow(("drvNetSnifferDetach: pDrvIns: %p, fFlags: %u\n", pDrvIns, fFlags));
313 RTCritSectEnter(&pThis->XmitLock);
314 pThis->pIBelowNet = NULL;
315 RTCritSectLeave(&pThis->XmitLock);
316}
317
318
319/**
320 * @interface_method_impl{PDMDRVREG,pfnAttach}
321 */
322static DECLCALLBACK(int) drvNetSnifferAttach(PPDMDRVINS pDrvIns, uint32_t fFlags)
323{
324 PDRVNETSNIFFER pThis = PDMINS_2_DATA(pDrvIns, PDRVNETSNIFFER);
325 LogFlow(("drvNetSnifferAttach/#%#x: fFlags=%#x\n", pDrvIns->iInstance, fFlags));
326 RTCritSectEnter(&pThis->XmitLock);
327
328 /*
329 * Query the network connector interface.
330 */
331 PPDMIBASE pBaseDown;
332 int rc = PDMDrvHlpAttach(pDrvIns, fFlags, &pBaseDown);
333 if ( rc == VERR_PDM_NO_ATTACHED_DRIVER
334 || rc == VERR_PDM_CFG_MISSING_DRIVER_NAME)
335 {
336 pThis->pIBelowNet = NULL;
337 rc = VINF_SUCCESS;
338 }
339 else if (RT_SUCCESS(rc))
340 {
341 pThis->pIBelowNet = PDMIBASE_QUERY_INTERFACE(pBaseDown, PDMINETWORKUP);
342 if (pThis->pIBelowNet)
343 rc = VINF_SUCCESS;
344 else
345 {
346 AssertMsgFailed(("Configuration error: the driver below didn't export the network connector interface!\n"));
347 rc = VERR_PDM_MISSING_INTERFACE_BELOW;
348 }
349 }
350 else
351 AssertMsgFailed(("Failed to attach to driver below! rc=%Rrc\n", rc));
352
353 RTCritSectLeave(&pThis->XmitLock);
354 return VINF_SUCCESS;
355}
356
357
358/**
359 * @interface_method_impl{PDMDRVREG,pfnDestruct}
360 */
361static DECLCALLBACK(void) drvNetSnifferDestruct(PPDMDRVINS pDrvIns)
362{
363 PDRVNETSNIFFER pThis = PDMINS_2_DATA(pDrvIns, PDRVNETSNIFFER);
364 PDMDRV_CHECK_VERSIONS_RETURN_VOID(pDrvIns);
365
366 if (RTCritSectIsInitialized(&pThis->Lock))
367 RTCritSectDelete(&pThis->Lock);
368
369 if (RTCritSectIsInitialized(&pThis->XmitLock))
370 RTCritSectDelete(&pThis->XmitLock);
371
372 if (pThis->hFile != NIL_RTFILE)
373 {
374 RTFileClose(pThis->hFile);
375 pThis->hFile = NIL_RTFILE;
376 }
377}
378
379
380/**
381 * @interface_method_impl{Construct a NAT network transport driver instance,
382 * PDMDRVREG,pfnDestruct}
383 */
384static DECLCALLBACK(int) drvNetSnifferConstruct(PPDMDRVINS pDrvIns, PCFGMNODE pCfg, uint32_t fFlags)
385{
386 PDMDRV_CHECK_VERSIONS_RETURN(pDrvIns);
387 PDRVNETSNIFFER pThis = PDMINS_2_DATA(pDrvIns, PDRVNETSNIFFER);
388 PCPDMDRVHLPR3 pHlp = pDrvIns->pHlpR3;
389
390 LogFlow(("drvNetSnifferConstruct:\n"));
391
392 /*
393 * Init the static parts.
394 */
395 pThis->pDrvIns = pDrvIns;
396 pThis->hFile = NIL_RTFILE;
397 /* The pcap file *must* start at time offset 0,0. */
398 pThis->StartNanoTS = RTTimeNanoTS() - RTTimeProgramNanoTS();
399 /* IBase */
400 pDrvIns->IBase.pfnQueryInterface = drvNetSnifferQueryInterface;
401 /* INetworkUp */
402 pThis->INetworkUp.pfnBeginXmit = drvNetSnifferUp_BeginXmit;
403 pThis->INetworkUp.pfnAllocBuf = drvNetSnifferUp_AllocBuf;
404 pThis->INetworkUp.pfnFreeBuf = drvNetSnifferUp_FreeBuf;
405 pThis->INetworkUp.pfnSendBuf = drvNetSnifferUp_SendBuf;
406 pThis->INetworkUp.pfnEndXmit = drvNetSnifferUp_EndXmit;
407 pThis->INetworkUp.pfnSetPromiscuousMode = drvNetSnifferUp_SetPromiscuousMode;
408 pThis->INetworkUp.pfnNotifyLinkChanged = drvNetSnifferUp_NotifyLinkChanged;
409 /* INetworkDown */
410 pThis->INetworkDown.pfnWaitReceiveAvail = drvNetSnifferDown_WaitReceiveAvail;
411 pThis->INetworkDown.pfnReceive = drvNetSnifferDown_Receive;
412 pThis->INetworkDown.pfnXmitPending = drvNetSnifferDown_XmitPending;
413 /* INetworkConfig */
414 pThis->INetworkConfig.pfnGetMac = drvNetSnifferDownCfg_GetMac;
415 pThis->INetworkConfig.pfnGetLinkState = drvNetSnifferDownCfg_GetLinkState;
416 pThis->INetworkConfig.pfnSetLinkState = drvNetSnifferDownCfg_SetLinkState;
417
418 /*
419 * Create the locks.
420 */
421 int rc = RTCritSectInit(&pThis->Lock);
422 AssertRCReturn(rc, rc);
423 rc = RTCritSectInit(&pThis->XmitLock);
424 AssertRCReturn(rc, rc);
425
426 /*
427 * Validate the config.
428 */
429 PDMDRV_VALIDATE_CONFIG_RETURN(pDrvIns, "File", "");
430
431 if (pHlp->pfnCFGMGetFirstChild(pCfg))
432 LogRel(("NetSniffer: Found child config entries -- are you trying to redirect ports?\n"));
433
434 /*
435 * Get the filename.
436 */
437 rc = pHlp->pfnCFGMQueryString(pCfg, "File", pThis->szFilename, sizeof(pThis->szFilename));
438 if (rc == VERR_CFGM_VALUE_NOT_FOUND)
439 {
440 if (pDrvIns->iInstance > 0)
441 RTStrPrintf(pThis->szFilename, sizeof(pThis->szFilename), "./VBox-%x-%u.pcap", RTProcSelf(), pDrvIns->iInstance);
442 else
443 RTStrPrintf(pThis->szFilename, sizeof(pThis->szFilename), "./VBox-%x.pcap", RTProcSelf());
444 }
445
446 else if (RT_FAILURE(rc))
447 {
448 AssertMsgFailed(("Failed to query \"File\", rc=%Rrc.\n", rc));
449 return rc;
450 }
451
452 /*
453 * Query the network port interface.
454 */
455 pThis->pIAboveNet = PDMIBASE_QUERY_INTERFACE(pDrvIns->pUpBase, PDMINETWORKDOWN);
456 if (!pThis->pIAboveNet)
457 {
458 AssertMsgFailed(("Configuration error: the above device/driver didn't export the network port interface!\n"));
459 return VERR_PDM_MISSING_INTERFACE_ABOVE;
460 }
461
462 /*
463 * Query the network config interface.
464 */
465 pThis->pIAboveConfig = PDMIBASE_QUERY_INTERFACE(pDrvIns->pUpBase, PDMINETWORKCONFIG);
466 if (!pThis->pIAboveConfig)
467 {
468 AssertMsgFailed(("Configuration error: the above device/driver didn't export the network config interface!\n"));
469 return VERR_PDM_MISSING_INTERFACE_ABOVE;
470 }
471
472 /*
473 * Query the network connector interface.
474 */
475 PPDMIBASE pBaseDown;
476 rc = PDMDrvHlpAttach(pDrvIns, fFlags, &pBaseDown);
477 if ( rc == VERR_PDM_NO_ATTACHED_DRIVER
478 || rc == VERR_PDM_CFG_MISSING_DRIVER_NAME)
479 pThis->pIBelowNet = NULL;
480 else if (RT_SUCCESS(rc))
481 {
482 pThis->pIBelowNet = PDMIBASE_QUERY_INTERFACE(pBaseDown, PDMINETWORKUP);
483 if (!pThis->pIBelowNet)
484 {
485 AssertMsgFailed(("Configuration error: the driver below didn't export the network connector interface!\n"));
486 return VERR_PDM_MISSING_INTERFACE_BELOW;
487 }
488 }
489 else
490 {
491 AssertMsgFailed(("Failed to attach to driver below! rc=%Rrc\n", rc));
492 return rc;
493 }
494
495 /*
496 * Open output file / pipe.
497 */
498 rc = RTFileOpen(&pThis->hFile, pThis->szFilename,
499 RTFILE_O_WRITE | RTFILE_O_CREATE_REPLACE | RTFILE_O_DENY_WRITE);
500 if (RT_FAILURE(rc))
501 return PDMDrvHlpVMSetError(pDrvIns, rc, RT_SRC_POS,
502 N_("Netsniffer cannot open '%s' for writing. The directory must exist and it must be writable for the current user"), pThis->szFilename);
503
504 char *pszPathReal = RTPathRealDup(pThis->szFilename);
505 if (pszPathReal)
506 {
507 LogRel(("NetSniffer: Sniffing to '%s'\n", pszPathReal));
508 RTStrFree(pszPathReal);
509 }
510 else
511 LogRel(("NetSniffer: Sniffing to '%s'\n", pThis->szFilename));
512
513 /*
514 * Write pcap header.
515 * Some time has gone by since capturing pThis->StartNanoTS so get the
516 * current time again.
517 */
518 PcapFileHdr(pThis->hFile, RTTimeNanoTS());
519
520 return VINF_SUCCESS;
521}
522
523
524
525/**
526 * Network sniffer filter driver registration record.
527 */
528const PDMDRVREG g_DrvNetSniffer =
529{
530 /* u32Version */
531 PDM_DRVREG_VERSION,
532 /* szName */
533 "NetSniffer",
534 /* szRCMod */
535 "",
536 /* szR0Mod */
537 "",
538 /* pszDescription */
539 "Network Sniffer Filter Driver",
540 /* fFlags */
541 PDM_DRVREG_FLAGS_HOST_BITS_DEFAULT,
542 /* fClass. */
543 PDM_DRVREG_CLASS_NETWORK,
544 /* cMaxInstances */
545 UINT32_MAX,
546 /* cbInstance */
547 sizeof(DRVNETSNIFFER),
548 /* pfnConstruct */
549 drvNetSnifferConstruct,
550 /* pfnDestruct */
551 drvNetSnifferDestruct,
552 /* pfnRelocate */
553 NULL,
554 /* pfnIOCtl */
555 NULL,
556 /* pfnPowerOn */
557 NULL,
558 /* pfnReset */
559 NULL,
560 /* pfnSuspend */
561 NULL,
562 /* pfnResume */
563 NULL,
564 /* pfnAttach */
565 drvNetSnifferAttach,
566 /* pfnDetach */
567 drvNetSnifferDetach,
568 /* pfnPowerOff */
569 NULL,
570 /* pfnSoftReset */
571 NULL,
572 /* u32EndVersion */
573 PDM_DRVREG_VERSION
574};
575
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use