VirtualBox

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

Last change on this file since 49435 was 45061, checked in by vboxsync, 12 years ago

Review of PDM driver destructors making sure that variables they use are correctly initialized in the constructor. Found several RTFileClose(0) cases.

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