VirtualBox

source: vbox/trunk/src/VBox/HostDrivers/VBoxNetFlt/win/VBoxNetFltPt-win.c@ 32189

Last change on this file since 32189 was 29616, checked in by vboxsync, 14 years ago

netflt/win: fix more bug in loopback packet handling

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 81.8 KB
Line 
1/* $Id: VBoxNetFltPt-win.c 29616 2010-05-18 11:55:55Z vboxsync $ */
2/** @file
3 * VBoxNetFlt - Network Filter Driver (Host), Windows Specific Code. Protocol edge of ndis filter driver
4 */
5
6/*
7 * Copyright (C) 2008 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 * Based in part on Microsoft DDK sample code for Ndis Intermediate Miniport passthru driver sample.
19 * Copyright (c) 1993-1999, Microsoft Corporation
20 */
21
22#include "VBoxNetFltCommon-win.h"
23
24#ifdef VBOXNETADP
25# error "No protocol edge"
26#endif
27
28/** protocol handle */
29static NDIS_HANDLE g_hProtHandle = NULL;
30/** medium array used while opening underlying adaprot
31 * we are actually binding to NdisMedium802_3 and NdisMediumWan
32 * as specified in VBoxNetFlt.inf:
33 * HKR, Ndi\Interfaces, FilterMediaTypes, , "ethernet, wan" */
34static NDIS_MEDIUM g_aMediumArray[] =
35 {
36 /* Ethernet */
37 NdisMedium802_3,
38 /* Wan */
39 NdisMediumWan
40 };
41
42/**
43 * performs binding to the given adapter
44 */
45#ifdef VBOX_NETFLT_ONDEMAND_BIND
46DECLHIDDEN(NDIS_STATUS) vboxNetFltWinPtDoBinding(IN PADAPT pAdapt)
47#else
48DECLHIDDEN(NDIS_STATUS) vboxNetFltWinPtDoBinding(IN PADAPT pAdapt, IN PNDIS_STRING pOurDeviceName, IN PNDIS_STRING pBindToDeviceName)
49#endif
50{
51 UINT MediumIndex;
52 NDIS_STATUS Status, Sts;
53
54 Assert(pAdapt->PTState.PowerState == NdisDeviceStateD3);
55 Assert(pAdapt->PTState.OpState == kVBoxNetDevOpState_Deinitialized);
56 Assert(KeGetCurrentIrql() == PASSIVE_LEVEL);
57
58 vboxNetFltWinSetOpState(&pAdapt->PTState, kVBoxNetDevOpState_Initializing);
59
60 do
61 {
62// NDIS_STATUS TmpStatus;
63 /* copy the bind to dev name to our buffer */
64#ifdef VBOX_NETFLT_ONDEMAND_BIND
65 NDIS_STRING BindToDeviceName;
66 PNDIS_STRING pBindToDeviceName;
67 PVBOXNETFLTINS pThis = PADAPT_2_PVBOXNETFLTINS(pAdapt);
68 PWSTR pUnicode;
69 ULONG cbUnicode;
70 ANSI_STRING AnsiStr;
71
72 /* most Rtlxx functions we are using here require this */
73 Assert(KeGetCurrentIrql() == PASSIVE_LEVEL);
74
75 RtlInitAnsiString(&AnsiStr, pThis->szName);
76 cbUnicode = RtlAnsiStringToUnicodeSize(&AnsiStr);
77
78 pUnicode = alloca(cbUnicode);
79 BindToDeviceName.Buffer = pUnicode;
80 BindToDeviceName.MaximumLength = (USHORT)cbUnicode;
81
82 Status = RtlAnsiStringToUnicodeString(&BindToDeviceName, &AnsiStr, FALSE);
83 if(!NT_SUCCESS(Status))
84 {
85 Assert(0);
86 break;
87 }
88
89 pBindToDeviceName = &BindToDeviceName;
90#else
91 Status = vboxNetFltWinCopyString(&pAdapt->DeviceName, pOurDeviceName);
92 if(Status != NDIS_STATUS_SUCCESS)
93 {
94 Assert(0);
95 break;
96 }
97#endif
98
99 vboxNetFltWinSetPowerState(&pAdapt->PTState, NdisDeviceStateD0);
100 pAdapt->Status = NDIS_STATUS_SUCCESS;
101
102 NdisResetEvent(&pAdapt->hEvent);
103
104 /*
105 * Now open the adapter below and complete the initialization
106 */
107 NdisOpenAdapter(&Status,
108 &Sts,
109 &pAdapt->hBindingHandle,
110 &MediumIndex,
111 g_aMediumArray,
112 sizeof(g_aMediumArray)/sizeof(NDIS_MEDIUM),
113 g_hProtHandle,
114 pAdapt,
115 pBindToDeviceName,
116 0,
117 NULL);
118
119 if (Status == NDIS_STATUS_PENDING)
120 {
121 NdisWaitEvent(&pAdapt->hEvent, 0);
122 Status = pAdapt->Status;
123 }
124
125 Assert(Status == NDIS_STATUS_SUCCESS);
126 if(Status != NDIS_STATUS_SUCCESS)
127 {
128 vboxNetFltWinSetOpState(&pAdapt->PTState, kVBoxNetDevOpState_Deinitialized);
129 pAdapt->hBindingHandle = NULL;
130 LogRel(("NdisOpenAdapter failed, Status (0c%x)", Status));
131 break;
132 }
133
134 Assert(pAdapt->hBindingHandle);
135
136 pAdapt->Medium = g_aMediumArray[MediumIndex];
137 vboxNetFltWinSetOpState(&pAdapt->PTState, kVBoxNetDevOpState_Initialized);
138
139#ifndef VBOX_NETFLT_ONDEMAND_BIND
140 Status = vboxNetFltWinMpInitializeDevideInstance(pAdapt);
141 if (Status != NDIS_STATUS_SUCCESS)
142 {
143 Log(("BindAdapter: Adapt %p, IMInitializeDeviceInstance error %x\n",
144 pAdapt, Status));
145
146 vboxNetFltWinSetOpState(&pAdapt->PTState, kVBoxNetDevOpState_Deinitializing);
147 vboxNetFltWinPtCloseAdapter(pAdapt, &Sts);
148 vboxNetFltWinSetOpState(&pAdapt->PTState, kVBoxNetDevOpState_Deinitialized);
149 break;
150 }
151#endif
152 } while(0);
153
154 return Status;
155}
156
157/**
158 * Called by NDIS to bind to a miniport below.
159 * @param Status - Return status of bind here.
160 * @param BindContext - Can be passed to NdisCompleteBindAdapter if this call is pended.
161 * @param DeviceName - Device name to bind to. This is passed to NdisOpenAdapter.
162 * @param SystemSpecific1 - Can be passed to NdisOpenProtocolConfiguration to read per-binding information
163 * @paran SystemSpecific2 - Unused
164 * @return NDIS_STATUS_PENDING if this call is pended. In this case call NdisCompleteBindAdapter to complete.
165 * Anything else Completes this call synchronously */
166static VOID
167vboxNetFltWinPtBindAdapter(
168 OUT PNDIS_STATUS pStatus,
169 IN NDIS_HANDLE BindContext,
170 IN PNDIS_STRING pDeviceName,
171 IN PVOID SystemSpecific1,
172 IN PVOID SystemSpecific2
173 )
174{
175#ifdef VBOX_NETFLT_ONDEMAND_BIND
176 /* we initiate the binding ourselves by calling NdisOpenAdapter */
177 LogFlow(("==> Protocol BindAdapter\n"));
178 Assert(0);
179 *pStatus = NDIS_STATUS_OPEN_FAILED;
180 LogFlow(("<== Protocol BindAdapter\n"));
181 return;
182#else
183 NDIS_HANDLE ConfigHandle = NULL;
184 PNDIS_CONFIGURATION_PARAMETER Param;
185 NDIS_STRING DeviceStr = NDIS_STRING_CONST("UpperBindings");
186 PADAPT pAdapt = NULL;
187
188 UNREFERENCED_PARAMETER(BindContext);
189 UNREFERENCED_PARAMETER(SystemSpecific2);
190
191 LogFlow(("==> Protocol BindAdapter\n"));
192
193 do
194 {
195 /* Access the configuration section for our binding-specific
196 * parameters. */
197
198 NdisOpenProtocolConfiguration(pStatus,
199 &ConfigHandle,
200 (PNDIS_STRING)SystemSpecific1);
201
202 if (*pStatus != NDIS_STATUS_SUCCESS)
203 {
204 break;
205 }
206
207 /* Read the "UpperBindings" reserved key that contains a list
208 * of device names representing our miniport instances corresponding
209 * to this lower binding. Since this is a 1:1 IM driver, this key
210 * contains exactly one name.
211 *
212 * If we want to implement a N:1 mux driver (N adapter instances
213 * over a single lower binding), then UpperBindings will be a
214 * MULTI_SZ containing a list of device names - we would loop through
215 * this list, calling NdisIMInitializeDeviceInstanceEx once for
216 * each name in it. */
217
218 NdisReadConfiguration(pStatus,
219 &Param,
220 ConfigHandle,
221 &DeviceStr,
222 NdisParameterString);
223 if (*pStatus != NDIS_STATUS_SUCCESS)
224 {
225 break;
226 }
227
228 *pStatus = vboxNetFltWinPtInitBind(&pAdapt, &Param->ParameterData.StringData, pDeviceName);
229 if (*pStatus != NDIS_STATUS_SUCCESS)
230 {
231 break;
232 }
233 } while(FALSE);
234
235 /*
236 * Close the configuration handle now - see comments above with
237 * the call to NdisIMInitializeDeviceInstanceEx.
238 */
239 if (ConfigHandle != NULL)
240 {
241 NdisCloseConfiguration(ConfigHandle);
242 }
243
244 LogFlow(("<== Protocol BindAdapter: pAdapt %p, Status %x\n", pAdapt, *pStatus));
245#endif
246}
247
248/**
249 * Completion routine for NdisOpenAdapter issued from within the vboxNetFltWinPtBindAdapter. Simply
250 * unblock the caller.
251 *
252 * @param ProtocolBindingContext Pointer to the adapter
253 * @param Status Status of the NdisOpenAdapter call
254 * @param OpenErrorStatus Secondary status(ignored by us).
255 * @return None
256 * */
257static VOID
258vboxNetFltWinPtOpenAdapterComplete(
259 IN NDIS_HANDLE ProtocolBindingContext,
260 IN NDIS_STATUS Status,
261 IN NDIS_STATUS OpenErrorStatus
262 )
263{
264 PADAPT pAdapt =(PADAPT)ProtocolBindingContext;
265
266 UNREFERENCED_PARAMETER(OpenErrorStatus);
267
268 LogFlow(("==> vboxNetFltWinPtOpenAdapterComplete: Adapt %p, Status %x\n", pAdapt, Status));
269 if(pAdapt->Status == NDIS_STATUS_SUCCESS)
270 {
271 pAdapt->Status = Status;
272 }
273 NdisSetEvent(&pAdapt->hEvent);
274}
275
276DECLHIDDEN(NDIS_STATUS)
277vboxNetFltWinPtDoUnbinding(PADAPT pAdapt, bool bOnUnbind)
278{
279 NDIS_STATUS Status;
280#ifndef VBOX_NETFLT_ONDEMAND_BIND
281 PNDIS_PACKET PacketArray[MAX_RECEIVE_PACKET_ARRAY_SIZE];
282 ULONG NumberOfPackets = 0, i;
283 BOOLEAN CompleteRequest = FALSE;
284 BOOLEAN ReturnPackets = FALSE;
285 PVBOXNETFLTINS pNetFlt = PADAPT_2_PVBOXNETFLTINS(pAdapt);
286 RTSPINLOCKTMP Tmp = RTSPINLOCKTMP_INITIALIZER;
287 uint64_t NanoTS = RTTimeSystemNanoTS();
288#endif
289 int cPPUsage;
290
291 LogFlow(("==> vboxNetFltWinPtDoUnbinding: Adapt %p\n", pAdapt));
292
293 Assert(KeGetCurrentIrql() == PASSIVE_LEVEL);
294
295#ifndef VBOX_NETFLT_ONDEMAND_BIND
296 Assert(vboxNetFltWinGetOpState(&pAdapt->PTState) == kVBoxNetDevOpState_Initialized);
297 /*
298 * Set the flag that the miniport below is unbinding, so the request handlers will
299 * fail any request comming later
300 */
301 RTSpinlockAcquireNoInts(pNetFlt->hSpinlock, &Tmp);
302
303 ASMAtomicUoWriteBool(&pNetFlt->fDisconnectedFromHost, true);
304 ASMAtomicUoWriteBool(&pNetFlt->fRediscoveryPending, false);
305 ASMAtomicUoWriteU64(&pNetFlt->NanoTSLastRediscovery, NanoTS);
306
307// pAdapt->PTState.DeviceState = NdisDeviceStateD3;
308// pAdapt->MPState.DeviceState = NdisDeviceStateD3;
309 vboxNetFltWinSetOpState(&pAdapt->PTState, kVBoxNetDevOpState_Deinitializing);
310 if(!bOnUnbind)
311 {
312 vboxNetFltWinSetOpState(&pAdapt->MPState, kVBoxNetDevOpState_Deinitializing);
313 }
314
315 if (pAdapt->bQueuedRequest == TRUE)
316 {
317 pAdapt->bQueuedRequest = FALSE;
318 CompleteRequest = TRUE;
319 }
320 if (pAdapt->cReceivedPacketCount > 0)
321 {
322
323 NdisMoveMemory(PacketArray,
324 pAdapt->aReceivedPackets,
325 pAdapt->cReceivedPacketCount * sizeof(PNDIS_PACKET));
326
327 NumberOfPackets = pAdapt->cReceivedPacketCount;
328
329 pAdapt->cReceivedPacketCount = 0;
330 ReturnPackets = TRUE;
331 }
332
333
334 RTSpinlockReleaseNoInts(pNetFlt->hSpinlock, &Tmp);
335
336 if (CompleteRequest == TRUE)
337 {
338 vboxNetFltWinPtRequestComplete(pAdapt,
339 &pAdapt->Request,
340 NDIS_STATUS_FAILURE );
341
342 }
343 if (ReturnPackets == TRUE)
344 {
345 for (i = 0; i < NumberOfPackets; i++)
346 {
347 vboxNetFltWinMpReturnPacket(pAdapt, PacketArray[i]);
348 }
349 }
350
351 vboxNetFltWinWaitDereference(&pAdapt->MPState);
352
353 vboxNetFltWinWaitDereference(&pAdapt->PTState);
354
355 /* check packet pool is empty */
356 cPPUsage = NdisPacketPoolUsage(pAdapt->hSendPacketPoolHandle);
357 Assert(cPPUsage == 0);
358 cPPUsage = NdisPacketPoolUsage(pAdapt->hRecvPacketPoolHandle);
359 Assert(cPPUsage == 0);
360 /* for debugging only, ignore the err in release */
361 NOREF(cPPUsage);
362
363 while (ASMAtomicUoReadBool((volatile bool *)&pAdapt->bOutstandingRequests))
364 {
365 /*
366 * sleep till outstanding requests complete
367 */
368 vboxNetFltWinSleep(2);
369 }
370
371 if(!bOnUnbind || !vboxNetFltWinMpDeInitializeDevideInstance(pAdapt, &Status))
372#endif /* #ifndef VBOX_NETFLT_ONDEMAND_BIND */
373 {
374 /*
375 * We need to do some work here.
376 * Close the binding below us
377 * and release the memory allocated.
378 */
379 vboxNetFltWinPtCloseAdapter(pAdapt, &Status);
380 vboxNetFltWinSetOpState(&pAdapt->PTState, kVBoxNetDevOpState_Deinitialized);
381
382 if(!bOnUnbind)
383 {
384 Assert(vboxNetFltWinGetOpState(&pAdapt->MPState) == kVBoxNetDevOpState_Deinitializing);
385 vboxNetFltWinSetOpState(&pAdapt->MPState, kVBoxNetDevOpState_Deinitialized);
386 }
387 else
388 {
389 Assert(vboxNetFltWinGetOpState(&pAdapt->MPState) == kVBoxNetDevOpState_Deinitialized);
390 }
391 }
392 else
393 {
394 Assert(vboxNetFltWinGetOpState(&pAdapt->MPState) == kVBoxNetDevOpState_Deinitialized);
395 }
396
397 LogFlow(("<== vboxNetFltWinPtDoUnbinding: Adapt %p\n", pAdapt));
398
399 return Status;
400}
401
402/**
403 * Called by NDIS when we are required to unbind to the adapter below.
404 * This functions shares functionality with the miniport's HaltHandler.
405 * The code should ensure that NdisCloseAdapter and NdisFreeMemory is called
406 * only once between the two functions
407 *
408 * @param Status Placeholder for return status
409 * @param ProtocolBindingContext Pointer to the adapter structure
410 * @param UnbindContext Context for NdisUnbindComplete() if this pends
411 * @return NONE */
412static VOID
413vboxNetFltWinPtUnbindAdapter(
414 OUT PNDIS_STATUS pStatus,
415 IN NDIS_HANDLE ProtocolBindingContext,
416 IN NDIS_HANDLE UnbindContext
417 )
418{
419 PADAPT pAdapt =(PADAPT)ProtocolBindingContext;
420 PVBOXNETFLTINS pNetFltIf = PADAPT_2_PVBOXNETFLTINS(pAdapt);
421
422 LogFlow(("==> vboxNetFltWinPtUnbindAdapter: Adapt %p\n", pAdapt));
423
424 *pStatus = vboxNetFltWinDetachFromInterface(pAdapt, true);
425 Assert(*pStatus == NDIS_STATUS_SUCCESS);
426
427 LogFlow(("<== vboxNetFltWinPtUnbindAdapter: Adapt %p\n", pAdapt));
428}
429
430/**
431 * protocol unload handler
432 */
433static VOID
434vboxNetFltWinPtUnloadProtocol(
435 VOID
436)
437{
438 vboxNetFltWinPtDeregister();
439 LogFlow(("vboxNetFltWinPtUnloadProtocol: done!\n"));
440}
441
442
443/**
444 * Completion for the CloseAdapter call.
445 *
446 * @param ProtocolBindingContext Pointer to the adapter structure
447 * @param Status Completion status
448 * @return None */
449static VOID
450vboxNetFltWinPtCloseAdapterComplete(
451 IN NDIS_HANDLE ProtocolBindingContext,
452 IN NDIS_STATUS Status
453 )
454{
455 PADAPT pAdapt =(PADAPT)ProtocolBindingContext;
456
457 LogFlow(("CloseAdapterComplete: Adapt %p, Status %x\n", pAdapt, Status));
458 if(pAdapt->Status == NDIS_STATUS_SUCCESS)
459 {
460 pAdapt->Status = Status;
461 }
462 NdisSetEvent(&pAdapt->hEvent);
463}
464
465
466/**
467 * Completion for the reset.
468 *
469 * @param ProtocolBindingContext Pointer to the adapter structure
470 * @param Status Completion status
471 * @return None */
472static VOID
473vboxNetFltWinPtResetComplete(
474 IN NDIS_HANDLE ProtocolBindingContext,
475 IN NDIS_STATUS Status
476 )
477{
478
479 UNREFERENCED_PARAMETER(ProtocolBindingContext);
480 UNREFERENCED_PARAMETER(Status);
481 /*
482 * We never issue a reset, so we should not be here.
483 */
484 Assert(0);
485}
486
487/**
488 * Completion handler for the previously posted request. All OIDS
489 * are completed by and sent to the same miniport that they were requested for.
490 * If Oid == OID_PNP_QUERY_POWER then the data structure needs to returned with all entries =
491 * NdisDeviceStateUnspecified
492 * @param ProtocolBindingContext Pointer to the adapter structure
493 * @param NdisRequest The posted request
494 * @param Status Completion status
495 * @return None
496 *
497 */
498DECLHIDDEN(VOID)
499vboxNetFltWinPtRequestComplete(
500 IN NDIS_HANDLE ProtocolBindingContext,
501 IN PNDIS_REQUEST NdisRequest,
502 IN NDIS_STATUS Status
503 )
504{
505 PADAPT pAdapt = (PADAPT)ProtocolBindingContext;
506 PNDIS_REQUEST pSynchRequest = pAdapt->pSynchRequest;
507#ifndef VBOX_NETFLT_ONDEMAND_BIND
508 NDIS_OID Oid = pAdapt->Request.DATA.SET_INFORMATION.Oid ;
509#endif
510
511 if(pSynchRequest == NdisRequest)
512 {
513 /* assynchronous completion of our synch request */
514
515 /*1.set the status */
516 pAdapt->fSynchCompletionStatus = Status;
517
518 /* 2. set event */
519 KeSetEvent(&pAdapt->hSynchCompletionEvent, 0, FALSE);
520
521 /* 3. return; */
522 return;
523 }
524#ifdef VBOX_NETFLT_ONDEMAND_BIND
525 Assert(0);
526 return;
527#else
528
529 /*
530 * Since our request is not outstanding anymore
531 */
532 Assert(pAdapt->bOutstandingRequests == TRUE);
533
534 pAdapt->bOutstandingRequests = FALSE;
535
536 /*
537 * Complete the Set or Query, and fill in the buffer for OID_PNP_CAPABILITIES, if need be.
538 */
539 switch (NdisRequest->RequestType)
540 {
541 case NdisRequestQueryInformation:
542
543 /*
544 * We never pass OID_PNP_QUERY_POWER down.
545 */
546 Assert(Oid != OID_PNP_QUERY_POWER);
547
548 if ((Oid == OID_PNP_CAPABILITIES) && (Status == NDIS_STATUS_SUCCESS))
549 {
550 vboxNetFltWinMpQueryPNPCapabilities(pAdapt, &Status);
551 }
552 *pAdapt->BytesReadOrWritten = NdisRequest->DATA.QUERY_INFORMATION.BytesWritten;
553 *pAdapt->BytesNeeded = NdisRequest->DATA.QUERY_INFORMATION.BytesNeeded;
554
555 if ((Oid == OID_GEN_MAC_OPTIONS) && (Status == NDIS_STATUS_SUCCESS))
556 {
557 /* save mac options for adaptor below us to use it with the NdisCopyLookaheadData when our ProtocolReceive is called */
558 pAdapt->fMacOptions = *(PULONG)NdisRequest->DATA.QUERY_INFORMATION.InformationBuffer;
559#ifndef VBOX_LOOPBACK_USEFLAGS
560 /*
561 * Remove the no-loopback bit from mac-options. In essence we are
562 * telling NDIS that we can handle loopback. We don't, but the
563 * interface below us does. If we do not do this, then loopback
564 * processing happens both below us and above us. This is wasteful
565 * at best and if Netmon is running, it will see multiple copies
566 * of loopback packets when sniffing above us.
567 *
568 * Only the lowest miniport is a stack of layered miniports should
569 * ever report this bit set to NDIS.
570 */
571 *(PULONG)NdisRequest->DATA.QUERY_INFORMATION.InformationBuffer &= ~NDIS_MAC_OPTION_NO_LOOPBACK;
572#else
573 /* we have to catch loopbacks from the underlying driver, so no duplications will occur,
574 * just indicate NDIS to handle loopbacks for the packets coming from the protocol */
575 *(PULONG)NdisRequest->DATA.QUERY_INFORMATION.InformationBuffer |= NDIS_MAC_OPTION_NO_LOOPBACK;
576#endif
577 }
578 if(Oid == OID_GEN_CURRENT_PACKET_FILTER && VBOXNETFLT_PROMISCUOUS_SUPPORTED(pAdapt))
579 {
580 /* we're here _ONLY_ in the passthru mode */
581 Assert(pAdapt->fProcessingPacketFilter == VBOXNETFLT_PFP_PASSTHRU);
582 if(pAdapt->fProcessingPacketFilter == VBOXNETFLT_PFP_PASSTHRU)
583 {
584 PVBOXNETFLTINS pNetFltIf = PADAPT_2_PVBOXNETFLTINS(pAdapt);
585 Assert(pNetFltIf->enmTrunkState != INTNETTRUNKIFSTATE_ACTIVE);
586 vboxNetFltWinDereferenceModePassThru(pNetFltIf);
587 vboxNetFltWinDereferenceAdapt(pAdapt);
588 }
589
590 if(Status == NDIS_STATUS_SUCCESS)
591 {
592 /* the filter request is issued below only in case netflt is not active,
593 * simply update the cache here */
594 /* cache the filter used by upper protocols */
595 pAdapt->fUpperProtocolSetFilter = *(PULONG)NdisRequest->DATA.QUERY_INFORMATION.InformationBuffer;
596 pAdapt->bUpperProtSetFilterInitialized = true;
597 }
598 }
599
600
601 NdisMQueryInformationComplete(pAdapt->hMiniportHandle,
602 Status);
603 break;
604
605 case NdisRequestSetInformation:
606
607 Assert( Oid != OID_PNP_SET_POWER);
608
609 if(Oid == OID_GEN_CURRENT_PACKET_FILTER && VBOXNETFLT_PROMISCUOUS_SUPPORTED(pAdapt))
610 {
611 PVBOXNETFLTINS pNetFltIf = PADAPT_2_PVBOXNETFLTINS(pAdapt);
612 Assert(Status == NDIS_STATUS_SUCCESS);
613 if(pAdapt->fProcessingPacketFilter == VBOXNETFLT_PFP_NETFLT)
614 {
615 Assert(pNetFltIf->enmTrunkState == INTNETTRUNKIFSTATE_ACTIVE);
616 if(Status == NDIS_STATUS_SUCCESS)
617 {
618 pAdapt->fOurSetFilter = *((PULONG)pAdapt->Request.DATA.SET_INFORMATION.InformationBuffer);
619 Assert(pAdapt->fOurSetFilter == NDIS_PACKET_TYPE_PROMISCUOUS);
620 }
621 vboxNetFltWinDereferenceNetFlt(pNetFltIf);
622 vboxNetFltWinDereferenceAdapt(pAdapt);
623 pAdapt->fProcessingPacketFilter = 0;
624 }
625 else if(pAdapt->fProcessingPacketFilter == VBOXNETFLT_PFP_PASSTHRU)
626 {
627 Assert(pNetFltIf->enmTrunkState != INTNETTRUNKIFSTATE_ACTIVE);
628
629 if(Status == NDIS_STATUS_SUCCESS)
630 {
631 /* the request was issued when the netflt was not active, simply update the cache here */
632 pAdapt->fUpperProtocolSetFilter = *((PULONG)pAdapt->Request.DATA.SET_INFORMATION.InformationBuffer);
633 pAdapt->bUpperProtSetFilterInitialized = true;
634 }
635 vboxNetFltWinDereferenceModePassThru(pNetFltIf);
636 vboxNetFltWinDereferenceAdapt(pAdapt);
637 pAdapt->fProcessingPacketFilter = 0;
638 }
639 }
640
641
642 *pAdapt->BytesReadOrWritten = NdisRequest->DATA.SET_INFORMATION.BytesRead;
643 *pAdapt->BytesNeeded = NdisRequest->DATA.SET_INFORMATION.BytesNeeded;
644 NdisMSetInformationComplete(pAdapt->hMiniportHandle,
645 Status);
646 break;
647
648 default:
649 Assert(0);
650 break;
651 }
652#endif
653}
654
655/**
656 * Status handler for the lower-edge(protocol).
657 *
658 * @param ProtocolBindingContext Pointer to the adapter structure
659 * @param GeneralStatus Status code
660 * @param StatusBuffer Status buffer
661 * @param StatusBufferSize Size of the status buffer
662 * @return None
663 */
664static VOID
665vboxNetFltWinPtStatus(
666 IN NDIS_HANDLE ProtocolBindingContext,
667 IN NDIS_STATUS GeneralStatus,
668 IN PVOID StatusBuffer,
669 IN UINT StatusBufferSize
670 )
671{
672#ifndef VBOX_NETFLT_ONDEMAND_BIND
673 PADAPT pAdapt = (PADAPT)ProtocolBindingContext;
674
675 /*
676 * Pass up this indication only if the upper edge miniport is initialized
677 * and powered on. Also ignore indications that might be sent by the lower
678 * miniport when it isn't at D0.
679 */
680 if (vboxNetFltWinReferenceAdapt(pAdapt))
681 {
682 Assert(pAdapt->hMiniportHandle);
683
684 if ((GeneralStatus == NDIS_STATUS_MEDIA_CONNECT) ||
685 (GeneralStatus == NDIS_STATUS_MEDIA_DISCONNECT))
686 {
687
688 pAdapt->LastIndicatedStatus = GeneralStatus;
689 }
690 NdisMIndicateStatus(pAdapt->hMiniportHandle,
691 GeneralStatus,
692 StatusBuffer,
693 StatusBufferSize);
694
695 vboxNetFltWinDereferenceAdapt(pAdapt);
696 }
697 /*
698 * Save the last indicated media status
699 */
700 else
701 {
702 if ((pAdapt->hMiniportHandle != NULL) &&
703 ((GeneralStatus == NDIS_STATUS_MEDIA_CONNECT) ||
704 (GeneralStatus == NDIS_STATUS_MEDIA_DISCONNECT)))
705 {
706 pAdapt->LatestUnIndicateStatus = GeneralStatus;
707 }
708 }
709#endif
710}
711
712/**
713 * status complete handler
714 */
715static VOID
716vboxNetFltWinPtStatusComplete(
717 IN NDIS_HANDLE ProtocolBindingContext
718 )
719{
720#ifndef VBOX_NETFLT_ONDEMAND_BIND
721 PADAPT pAdapt = (PADAPT)ProtocolBindingContext;
722
723 /*
724 * Pass up this indication only if the upper edge miniport is initialized
725 * and powered on. Also ignore indications that might be sent by the lower
726 * miniport when it isn't at D0.
727 */
728 if (vboxNetFltWinReferenceAdapt(pAdapt))
729 {
730 NdisMIndicateStatusComplete(pAdapt->hMiniportHandle);
731
732 vboxNetFltWinDereferenceAdapt(pAdapt);
733 }
734#endif
735}
736
737/**
738 * Called by NDIS when the miniport below had completed a send. We should
739 * complete the corresponding upper-edge send this represents.
740 *
741 * @param ProtocolBindingContext - Points to ADAPT structure
742 * @param Packet - Low level packet being completed
743 * @param Status - status of send
744 * @return None
745 */
746static VOID
747vboxNetFltWinPtSendComplete(
748 IN NDIS_HANDLE ProtocolBindingContext,
749 IN PNDIS_PACKET Packet,
750 IN NDIS_STATUS Status
751 )
752{
753 PADAPT pAdapt = (PADAPT)ProtocolBindingContext;
754 PNDIS_PACKET Pkt;
755
756 {
757 PSEND_RSVD SendRsvd;
758
759#if defined(DEBUG_NETFLT_PACKETS) || !defined(VBOX_LOOPBACK_USEFLAGS)
760 /* @todo: for optimization we could check only for netflt-mode packets
761 * do it for all for now */
762 vboxNetFltWinLbRemoveSendPacket(pAdapt, Packet);
763#endif
764// Assert(KeGetCurrentIrql() == DISPATCH_LEVEL);
765
766 SendRsvd = (PSEND_RSVD)(Packet->ProtocolReserved);
767 Pkt = SendRsvd->pOriginalPkt;
768
769#ifndef VBOX_NETFLT_ONDEMAND_BIND
770 if(Pkt)
771 {
772#ifndef WIN9X
773 NdisIMCopySendCompletePerPacketInfo (Pkt, Packet);
774#endif
775 NdisFreePacket(Packet);
776
777 /* the ptk was posted from the upperlying protocol */
778 NdisMSendComplete(pAdapt->hMiniportHandle,
779 Pkt,
780 Status);
781 }
782 else
783#else
784 /* TODO: should change the PSEND_RSVD structure as we no nolnger need to handle original packets
785 * because all packets are originated by us */
786 Assert(!Pkt);
787#endif
788 {
789 /* if the ptk is zerro - the ptk was originated by netFlt send/receive
790 * need to free packet buffers */
791 PVOID pBufToFree = SendRsvd->pBufToFree;
792
793 vboxNetFltWinFreeSGNdisPacket(Packet, !pBufToFree);
794 if(pBufToFree)
795 {
796 vboxNetFltWinMemFree(pBufToFree);
797 }
798 }
799 }
800
801 vboxNetFltWinDereferenceAdapt(pAdapt);
802}
803
804#ifndef VBOX_NETFLT_ONDEMAND_BIND
805
806/**
807 * removes searches for the packet in the list and removes it if found
808 * @return true if the packet was found and removed, false - otherwise
809 */
810static bool vboxNetFltWinRemovePacketFromList(PINTERLOCKED_SINGLE_LIST pList, PNDIS_PACKET pPacket)
811{
812 PTRANSFERDATA_RSVD pTDR = (PTRANSFERDATA_RSVD)pPacket->ProtocolReserved;
813 return vboxNetFltWinInterlockedSearchListEntry(pList, &pTDR->ListEntry,
814 true /* remove*/);
815}
816
817/**
818 * puts the packet to the tail of the list
819 */
820static void vboxNetFltWinPutPacketToList(PINTERLOCKED_SINGLE_LIST pList, PNDIS_PACKET pPacket, PNDIS_BUFFER pOrigBuffer)
821{
822 PTRANSFERDATA_RSVD pTDR = (PTRANSFERDATA_RSVD)pPacket->ProtocolReserved;
823 pTDR->pOriginalBuffer = pOrigBuffer;
824 vboxNetFltWinInterlockedPutTail(pList, &pTDR->ListEntry);
825}
826
827/**
828 * This is to queue the received packets and indicates them up if the given Packet
829 * status is NDIS_STATUS_RESOURCES, or the array is full.
830 *
831 * @param pAdapt - Pointer to the adpater structure.
832 * @param Packet - Pointer to the indicated packet.
833 * @param Indicate - Do the indication now.
834 * @return NONE
835 */
836static VOID
837vboxNetFltWinPtQueueReceivedPacket(
838 IN PADAPT pAdapt,
839 IN PNDIS_PACKET Packet,
840 IN BOOLEAN DoIndicate
841 )
842{
843 PNDIS_PACKET PacketArray[MAX_RECEIVE_PACKET_ARRAY_SIZE];
844 ULONG NumberOfPackets = 0, i;
845 bool bReturn = false;
846 PVBOXNETFLTINS pNetFlt = PADAPT_2_PVBOXNETFLTINS(pAdapt);
847 RTSPINLOCKTMP Tmp = RTSPINLOCKTMP_INITIALIZER;
848
849 Assert(KeGetCurrentIrql() == DISPATCH_LEVEL);
850 do{
851 RTSpinlockAcquireNoInts(pNetFlt->hSpinlock, &Tmp);
852
853 Assert(pAdapt->cReceivedPacketCount < MAX_RECEIVE_PACKET_ARRAY_SIZE);
854
855 /*
856 * pAdapt->ReceviePacketCount must be less than MAX_RECEIVE_PACKET_ARRAY_SIZE because
857 * the thread which held the pVElan->Lock before should already indicate the packet(s)
858 * up if pAdapt->ReceviePacketCount == MAX_RECEIVE_PACKET_ARRAY_SIZE.
859 */
860 pAdapt->aReceivedPackets[pAdapt->cReceivedPacketCount] = Packet;
861 pAdapt->cReceivedPacketCount++;
862
863 /* check the device state */
864 if(vboxNetFltWinGetPowerState(&pAdapt->PTState) != NdisDeviceStateD0
865 || vboxNetFltWinGetPowerState(&pAdapt->MPState) != NdisDeviceStateD0
866 || vboxNetFltWinGetOpState(&pAdapt->PTState) > kVBoxNetDevOpState_Initialized
867 || vboxNetFltWinGetOpState(&pAdapt->MPState) > kVBoxNetDevOpState_Initialized)
868 {
869 /* we need to return all packets */
870 bReturn = true;
871 }
872
873 /*
874 * If our receive packet array is full, or the miniport below indicated the packets
875 * with resources, do the indicatin now.
876 */
877
878 if ((pAdapt->cReceivedPacketCount == MAX_RECEIVE_PACKET_ARRAY_SIZE) || DoIndicate || bReturn)
879 {
880 NdisMoveMemory(PacketArray,
881 pAdapt->aReceivedPackets,
882 pAdapt->cReceivedPacketCount * sizeof(PNDIS_PACKET));
883
884 NumberOfPackets = pAdapt->cReceivedPacketCount;
885 /*
886 * So other thread can queue the received packets
887 */
888 pAdapt->cReceivedPacketCount = 0;
889
890 if(!bReturn)
891 {
892 DoIndicate = TRUE;
893 }
894 }
895 RTSpinlockReleaseNoInts(pNetFlt->hSpinlock, &Tmp);
896 } while(0);
897
898 if(!bReturn)
899 {
900 if(DoIndicate)
901 {
902 NdisMIndicateReceivePacket(pAdapt->hMiniportHandle, PacketArray, NumberOfPackets);
903 }
904 }
905 else
906 {
907 if (DoIndicate)
908 {
909 NumberOfPackets -= 1;
910 }
911 for (i = 0; i < NumberOfPackets; i++)
912 {
913 vboxNetFltWinMpReturnPacket(pAdapt, PacketArray[i]);
914 }
915 }
916}
917
918#endif
919
920static bool vboxNetFltWinPtTransferDataCompleteActive(IN PADAPT pAdapt,
921 IN PNDIS_PACKET pPacket,
922 IN NDIS_STATUS Status)
923{
924 PVBOXNETFLTINS pNetFltIf = PADAPT_2_PVBOXNETFLTINS(pAdapt);
925 PNDIS_BUFFER pBuffer;
926 PTRANSFERDATA_RSVD pTDR;
927
928 if(!vboxNetFltWinRemovePacketFromList(&pAdapt->TransferDataList, pPacket))
929 return false;
930
931 pTDR = (PTRANSFERDATA_RSVD)pPacket->ProtocolReserved;
932 Assert(pTDR);
933 Assert(pTDR->pOriginalBuffer);
934
935 do
936 {
937 NdisUnchainBufferAtFront(pPacket, &pBuffer);
938
939 Assert(pBuffer);
940
941 NdisFreeBuffer(pBuffer);
942
943 pBuffer = pTDR->pOriginalBuffer;
944
945 NdisChainBufferAtBack(pPacket, pBuffer);
946
947 /* data transfer was initiated when the netFlt was active
948 * the netFlt is still retained by us
949 * 1. check if loopback
950 * 2. enqueue packet
951 * 3. release netFlt */
952
953 if(Status == NDIS_STATUS_SUCCESS)
954 {
955
956#ifdef VBOX_LOOPBACK_USEFLAGS
957 if(vboxNetFltWinIsLoopedBackPacket(pPacket))
958 {
959 /* should not be here */
960 Assert(0);
961 }
962#else
963 PNDIS_PACKET pLb = vboxNetFltWinLbSearchLoopBack(pAdapt, pPacket, false);
964 if(pLb)
965 {
966#ifndef DEBUG_NETFLT_RECV_TRANSFERDATA
967 /* should not be here */
968 Assert(0);
969#endif
970 if(!vboxNetFltWinLbIsFromIntNet(pLb))
971 {
972 /* the packet is not from int net, need to pass it up to the host */
973 vboxNetFltWinPtQueueReceivedPacket(pAdapt, pPacket, FALSE);
974 /* dereference NetFlt, pAdapt will be dereferenced on Packet return */
975 vboxNetFltWinDereferenceNetFlt(pNetFltIf);
976 break;
977 }
978 }
979#endif
980 else
981 {
982 PRECV_RSVD pRecvRsvd;
983 /* 2. enqueue */
984 /* use the same packet info to put the packet in the processing packet queue */
985#ifdef VBOX_NETFLT_ONDEMAND_BIND
986# error "port me or remove VBOX_NETFLT_ONDEMAND_BIND"
987 PNDIS_BUFFER pBuffer;
988 PVOID pVA;
989 UINT cbLength;
990 uint32_t fFlags;
991
992 NdisQueryPacket(pPacket, NULL, NULL, &pBuffer, NULL);
993 NdisQueryBufferSafe(pBuffer, &pVA, &cbLength, NormalPagePriority);
994
995 fFlags = MACS_EQUAL(((PRTNETETHERHDR)pVA)->SrcMac, pNetFltIf->u.s.MacAddr) ?
996 PACKET_MINE | PACKET_SRC_HOST : PACKET_MINE;
997 SET_FLAGS_TO_INFO(pInfo, fFlags);
998
999 pRecvRsvd = (PRECV_RSVD)(pPacket->MiniportReserved);
1000 pRecvRsvd->pOriginalPkt = NULL;
1001 pRecvRsvd->pBufToFree = NULL;
1002
1003 NdisSetPacketFlags(pPacket, 0);
1004
1005 Status = vboxNetFltWinQuEnqueuePacket(pNetFltIf, pPacket, fFlags);
1006#else
1007 VBOXNETFLT_LBVERIFY(pNetFltIf, pPacket);
1008
1009 pRecvRsvd = (PRECV_RSVD)(pPacket->MiniportReserved);
1010 pRecvRsvd->pOriginalPkt = NULL;
1011 pRecvRsvd->pBufToFree = NULL;
1012
1013 NdisSetPacketFlags(pPacket, 0);
1014# ifdef VBOXNETFLT_NO_PACKET_QUEUE
1015 if (vboxNetFltWinPostIntnet(pNetFltIf, pPacket, 0))
1016 {
1017 /* drop it */
1018 vboxNetFltWinFreeSGNdisPacket(pPacket, true);
1019 vboxNetFltWinDereferenceAdapt(pAdapt);
1020 }
1021 else
1022 {
1023 NdisMIndicateReceivePacket(pAdapt->hMiniportHandle, &pPacket, 1);
1024 }
1025 vboxNetFltWinDereferenceNetFlt(pNetFltIf);
1026 break;
1027# else
1028 Status = vboxNetFltWinQuEnqueuePacket(pNetFltIf, pPacket, PACKET_MINE);
1029 if (Status == NDIS_STATUS_SUCCESS)
1030 {
1031 break;
1032 }
1033 Assert(0);
1034# endif
1035#endif
1036 }
1037 }
1038 else
1039 {
1040 Assert(0);
1041 }
1042 /* we are here because of error either in data transfer or in enqueueing the packet */
1043 vboxNetFltWinFreeSGNdisPacket(pPacket, true);
1044 vboxNetFltWinDereferenceNetFlt(pNetFltIf);
1045 vboxNetFltWinDereferenceAdapt(pAdapt);
1046 } while(0);
1047
1048 return true;
1049}
1050
1051/**
1052 * Entry point called by NDIS to indicate completion of a call by us
1053 * to NdisTransferData.
1054 *
1055 * See notes under SendComplete.
1056 */
1057static VOID
1058vboxNetFltWinPtTransferDataComplete(
1059 IN NDIS_HANDLE ProtocolBindingContext,
1060 IN PNDIS_PACKET pPacket,
1061 IN NDIS_STATUS Status,
1062 IN UINT BytesTransferred
1063 )
1064{
1065 PADAPT pAdapt =(PADAPT)ProtocolBindingContext;
1066 if(!vboxNetFltWinPtTransferDataCompleteActive(pAdapt, pPacket, Status))
1067 {
1068#ifndef VBOX_NETFLT_ONDEMAND_BIND
1069 if(pAdapt->hMiniportHandle)
1070 {
1071 NdisMTransferDataComplete(pAdapt->hMiniportHandle,
1072 pPacket,
1073 Status,
1074 BytesTransferred);
1075 }
1076
1077 vboxNetFltWinDereferenceAdapt(pAdapt);
1078#else
1079 /* we are here because we've failed to allocate packet info */
1080 Assert(0);
1081#endif
1082 }
1083}
1084#ifndef VBOX_NETFLT_ONDEMAND_BIND
1085/**
1086 * This routine process the queued the packet, if anything is fine, indicate the packet
1087 * up, otherwise, return the packet to the underlying miniports.
1088 *
1089 * @param pAdapt - Pointer to the adpater structure.
1090 * @param bReturn - if true the packets should be returned without indication to the upper protocol
1091 * @return None. */
1092DECLHIDDEN(VOID)
1093vboxNetFltWinPtFlushReceiveQueue(
1094 IN PADAPT pAdapt,
1095 IN bool bReturn
1096 )
1097{
1098
1099 PNDIS_PACKET PacketArray[MAX_RECEIVE_PACKET_ARRAY_SIZE];
1100 ULONG NumberOfPackets = 0, i;
1101 PVBOXNETFLTINS pNetFlt = PADAPT_2_PVBOXNETFLTINS(pAdapt);
1102 RTSPINLOCKTMP Tmp = RTSPINLOCKTMP_INITIALIZER;
1103
1104 do
1105 {
1106 RTSpinlockAcquireNoInts(pNetFlt->hSpinlock, &Tmp);
1107
1108 if (pAdapt->cReceivedPacketCount > 0)
1109 {
1110 NdisMoveMemory(PacketArray,
1111 pAdapt->aReceivedPackets,
1112 pAdapt->cReceivedPacketCount * sizeof(PNDIS_PACKET));
1113
1114 NumberOfPackets = pAdapt->cReceivedPacketCount;
1115 /*
1116 * So other thread can queue the received packets
1117 */
1118 pAdapt->cReceivedPacketCount = 0;
1119
1120 RTSpinlockReleaseNoInts(pNetFlt->hSpinlock, &Tmp);
1121
1122 if(!bReturn)
1123 {
1124 if(NumberOfPackets > 0)
1125 {
1126 Assert(pAdapt->hMiniportHandle);
1127
1128 /* we are here because the NetFlt is NOT active,
1129 * so no need for packet queueing here, simply indicate */
1130 NdisMIndicateReceivePacket(pAdapt->hMiniportHandle,
1131 PacketArray,
1132 NumberOfPackets);
1133 }
1134 break;
1135 }
1136 /*
1137 * We need return the packet here
1138 */
1139 for (i = 0; i < NumberOfPackets; i ++)
1140 {
1141 vboxNetFltWinMpReturnPacket(pAdapt, PacketArray[i]);
1142 }
1143
1144 /* break to ensure we do not call RTSpinlockRelease extra time */
1145 break;
1146 }
1147
1148 /* we are here only in case pAdapt->cReceivedPacketCount == 0 */
1149 RTSpinlockReleaseNoInts(pNetFlt->hSpinlock, &Tmp);
1150 } while (FALSE);
1151}
1152
1153/**
1154 * ReceivePacket handler. Called by NDIS if the miniport below supports
1155 * NDIS 4.0 style receives. Re-package the buffer chain in a new packet
1156 * and indicate the new packet to protocols above us. Any context for
1157 * packets indicated up must be kept in the MiniportReserved field.
1158 *
1159 * @param ProtocolBindingContext - Pointer to our adapter structure.
1160 * @param Packet - Pointer to the packet
1161 * @return INT == 0 -> We are done with the packet
1162 * != 0 -> We will keep the packet and call NdisReturnPackets() this
1163 * many times when done. */
1164static INT
1165vboxNetFltWinRecvPacketPassThru(
1166 IN PADAPT pAdapt,
1167 IN PNDIS_PACKET pPacket
1168 )
1169{
1170 NDIS_STATUS fStatus;
1171 PNDIS_PACKET pMyPacket;
1172
1173 Assert(KeGetCurrentIrql() == DISPATCH_LEVEL);
1174
1175 fStatus = vboxNetFltWinPrepareRecvPacket(pAdapt, pPacket, &pMyPacket, true);
1176
1177 Assert(pMyPacket);
1178
1179 if(pMyPacket != NULL)
1180 {
1181 if (fStatus == NDIS_STATUS_RESOURCES)
1182 {
1183 vboxNetFltWinPtQueueReceivedPacket(pAdapt, pMyPacket, TRUE);
1184
1185 /*
1186 * Our ReturnPackets handler will not be called for this packet.
1187 * We should reclaim it right here.
1188 */
1189 NdisDprFreePacket(pMyPacket);
1190
1191 return 0;
1192 }
1193
1194 vboxNetFltWinPtQueueReceivedPacket(pAdapt, pMyPacket, FALSE);
1195
1196 return 1;
1197 }
1198
1199 return 0;
1200}
1201
1202/**
1203 * process the packet receive in a "passthru" mode
1204 */
1205static NDIS_STATUS
1206vboxNetFltWinRecvPassThru(
1207 IN PADAPT pAdapt,
1208 IN PNDIS_PACKET pPacket)
1209{
1210
1211 NDIS_STATUS fStatus;
1212 PNDIS_PACKET pMyPacket;
1213 /*
1214 * The miniport below did indicate up a packet. Use information
1215 * from that packet to construct a new packet to indicate up.
1216 */
1217
1218 Assert(KeGetCurrentIrql() == DISPATCH_LEVEL);
1219
1220 /*
1221 * Get a packet off the pool and indicate that up
1222 */
1223 NdisDprAllocatePacket(&fStatus,
1224 &pMyPacket,
1225 pAdapt->hRecvPacketPoolHandle);
1226 Assert(fStatus == NDIS_STATUS_SUCCESS);
1227 if (fStatus == NDIS_STATUS_SUCCESS)
1228 {
1229 /*
1230 * Make our packet point to data from the original
1231 * packet. NOTE: this works only because we are
1232 * indicating a receive directly from the context of
1233 * our receive indication. If we need to queue this
1234 * packet and indicate it from another thread context,
1235 * we will also have to allocate a new buffer and copy
1236 * over the packet contents, OOB data and per-packet
1237 * information. This is because the packet data
1238 * is available only for the duration of this
1239 * receive indication call.
1240 */
1241 NDIS_PACKET_FIRST_NDIS_BUFFER(pMyPacket) = NDIS_PACKET_FIRST_NDIS_BUFFER(pPacket);
1242 NDIS_PACKET_LAST_NDIS_BUFFER(pMyPacket) = NDIS_PACKET_LAST_NDIS_BUFFER(pPacket);
1243
1244 /*
1245 * Get the original packet (it could be the same packet as the
1246 * one received or a different one based on the number of layered
1247 * miniports below) and set it on the indicated packet so the OOB
1248 * data is visible correctly at protocols above.
1249 */
1250 NDIS_SET_ORIGINAL_PACKET(pMyPacket, NDIS_GET_ORIGINAL_PACKET(pPacket));
1251 NDIS_SET_PACKET_HEADER_SIZE(pMyPacket, NDIS_GET_PACKET_HEADER_SIZE(pPacket));
1252
1253 /*
1254 * Copy packet flags.
1255 */
1256 NdisGetPacketFlags(pMyPacket) = NdisGetPacketFlags(pPacket);
1257
1258 /*
1259 * Force protocols above to make a copy if they want to hang
1260 * on to data in this packet. This is because we are in our
1261 * Receive handler (not ReceivePacket) and we can't return a
1262 * ref count from here.
1263 */
1264 NDIS_SET_PACKET_STATUS(pMyPacket, NDIS_STATUS_RESOURCES);
1265
1266 /*
1267 * By setting NDIS_STATUS_RESOURCES, we also know that we can reclaim
1268 * this packet as soon as the call to NdisMIndicateReceivePacket
1269 * returns.
1270 *
1271 * NOTE: we queue the packet and indicate this packet immediately with
1272 * the already queued packets together. We have to the queue the packet
1273 * first because some versions of NDIS might call protocols'
1274 * ReceiveHandler(not ReceivePacketHandler) if the packet indicate status
1275 * is NDIS_STATUS_RESOURCES. If the miniport below indicates an array of
1276 * packets, some of them with status NDIS_STATUS_SUCCESS, some of them
1277 * with status NDIS_STATUS_RESOURCES, vboxNetFltWinPtReceive might be called, by
1278 * doing this way, we preserve the receive order of packets.
1279 */
1280 vboxNetFltWinPtQueueReceivedPacket(pAdapt, pMyPacket, TRUE);
1281 /*
1282 * Reclaim the indicated packet. Since we had set its status
1283 * to NDIS_STATUS_RESOURCES, we are guaranteed that protocols
1284 * above are done with it.
1285 */
1286 NdisDprFreePacket(pMyPacket);
1287
1288 }
1289 return fStatus;
1290}
1291
1292#endif /* #ifndef VBOX_NETFLT_ONDEMAND_BIND */
1293
1294
1295
1296
1297/**
1298 * process the ProtocolReceive in an "active" mode
1299 *
1300 * @return NDIS_STATUS_SUCCESS - the packet is processed
1301 * NDIS_STATUS_PENDING - the packet is being processed, we are waiting for the ProtocolTransferDataComplete to be called
1302 * NDIS_STATUS_NOT_ACCEPTED - the packet is not needed - typically this is because this is a loopback packet
1303 * NDIS_STATUS_FAILURE - packet processing failed
1304 */
1305static NDIS_STATUS
1306vboxNetFltWinPtReceiveActive(
1307 IN PADAPT pAdapt,
1308 IN NDIS_HANDLE MacReceiveContext,
1309 IN PVOID pHeaderBuffer,
1310 IN UINT cbHeaderBuffer,
1311 IN PVOID pLookaheadBuffer,
1312 IN UINT cbLookaheadBuffer,
1313 IN UINT cbPacket
1314 )
1315{
1316 NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
1317
1318 do
1319 {
1320 if (cbHeaderBuffer != ETH_HEADER_SIZE)
1321 {
1322 Status = NDIS_STATUS_NOT_ACCEPTED;
1323 break;
1324 }
1325
1326#ifndef DEBUG_NETFLT_RECV_TRANSFERDATA
1327 if (cbPacket == cbLookaheadBuffer)
1328 {
1329 PVBOXNETFLTINS pNetFlt = PADAPT_2_PVBOXNETFLTINS(pAdapt);
1330 PINTNETSG pSG;
1331 PUCHAR pRcvData;
1332#ifndef VBOX_LOOPBACK_USEFLAGS
1333 PNDIS_PACKET pLb;
1334#endif
1335
1336 /* allocate SG buffer */
1337 Status = vboxNetFltWinAllocSG(cbPacket + cbHeaderBuffer, &pSG);
1338 if(Status != NDIS_STATUS_SUCCESS)
1339 {
1340 Assert(0);
1341 break;
1342 }
1343
1344 pRcvData = (PUCHAR)pSG->aSegs[0].pv;
1345
1346 NdisMoveMappedMemory(pRcvData, pHeaderBuffer, cbHeaderBuffer);
1347
1348 NdisCopyLookaheadData(pRcvData+cbHeaderBuffer,
1349 pLookaheadBuffer,
1350 cbLookaheadBuffer,
1351 pAdapt->fMacOptions);
1352#ifndef VBOX_LOOPBACK_USEFLAGS
1353 pLb = vboxNetFltWinLbSearchLoopBackBySG(pAdapt, pSG, false);
1354 if(pLb)
1355 {
1356#ifndef DEBUG_NETFLT_RECV_NOPACKET
1357 /* should not be here */
1358 Assert(0);
1359#endif
1360 if(!vboxNetFltWinLbIsFromIntNet(pLb))
1361 {
1362 PNDIS_PACKET pMyPacket;
1363 pMyPacket = vboxNetFltWinNdisPacketFromSG(pAdapt, /* PADAPT */
1364 pSG, /* PINTNETSG */
1365 pSG, /* PVOID pBufToFree */
1366 false, /* bool bToWire */
1367 false); /* bool bCopyMemory */
1368 if(pMyPacket)
1369 {
1370 vboxNetFltWinPtQueueReceivedPacket(pAdapt, pMyPacket, FALSE);
1371 /* dereference the NetFlt here & indicate SUCCESS, which would mean the caller would not do a dereference
1372 * the pAdapt dereference will be done on packet return */
1373 vboxNetFltWinDereferenceNetFlt(pNetFlt);
1374 Status = NDIS_STATUS_SUCCESS;
1375 }
1376 else
1377 {
1378 vboxNetFltWinMemFree(pSG);
1379 Status = NDIS_STATUS_FAILURE;
1380 }
1381 }
1382 else
1383 {
1384 vboxNetFltWinMemFree(pSG);
1385 Status = NDIS_STATUS_NOT_ACCEPTED;
1386 }
1387 break;
1388 }
1389#endif
1390 VBOXNETFLT_LBVERIFYSG(pNetFlt, pSG);
1391
1392 /* enqueue SG */
1393#ifdef VBOX_NETFLT_ONDEMAND_BIND
1394# ifdef VBOXNETFLT_NO_PACKET_QUEUE
1395# error "port me or remove VBOX_NETFLT_ONDEMAND_BIND"
1396# endif
1397 {
1398 uint32_t fFlags = MACS_EQUAL(((PRTNETETHERHDR)pRcvData)->SrcMac, pNetFlt->u.s.MacAddr) ?
1399 PACKET_SG | PACKET_MINE | PACKET_SRC_HOST : PACKET_SG | PACKET_MINE;
1400 Status = vboxNetFltWinQuEnqueuePacket(pNetFlt, pSG, fFlags);
1401 }
1402#else
1403# ifdef VBOXNETFLT_NO_PACKET_QUEUE
1404 if (vboxNetFltWinPostIntnet(pNetFlt, pSG, PACKET_SG))
1405 {
1406 /* drop it */
1407 vboxNetFltWinMemFree(pSG);
1408 vboxNetFltWinDereferenceAdapt(pAdapt);
1409 }
1410 else
1411 {
1412 PNDIS_PACKET pMyPacket = vboxNetFltWinNdisPacketFromSG(pAdapt, /* PADAPT */
1413 pSG, /* PINTNETSG */
1414 pSG, /* PVOID pBufToFree */
1415 false, /* bool bToWire */
1416 false); /* bool bCopyMemory */
1417 Assert(pMyPacket);
1418 if (pMyPacket)
1419 {
1420 NDIS_SET_PACKET_STATUS(pMyPacket, NDIS_STATUS_SUCCESS);
1421
1422 DBG_CHECK_PACKET_AND_SG(pMyPacket, pSG);
1423
1424 LogFlow(("non-ndis packet info, packet created (%p)\n", pMyPacket));
1425 NdisMIndicateReceivePacket(pAdapt->hMiniportHandle, &pMyPacket, 1);
1426 }
1427 else
1428 {
1429 vboxNetFltWinDereferenceAdapt(pAdapt);
1430 Status = NDIS_STATUS_RESOURCES;
1431 }
1432 }
1433 vboxNetFltWinDereferenceNetFlt(pNetFlt);
1434# else
1435 Status = vboxNetFltWinQuEnqueuePacket(pNetFlt, pSG, PACKET_SG | PACKET_MINE);
1436 if(Status != NDIS_STATUS_SUCCESS)
1437 {
1438 Assert(0);
1439 vboxNetFltWinMemFree(pSG);
1440 break;
1441 }
1442# endif
1443#endif
1444 }
1445 else
1446#endif /* #ifndef DEBUG_NETFLT_RECV_TRANSFERDATA */
1447 {
1448 PNDIS_PACKET pPacket;
1449 PNDIS_BUFFER pTransferBuffer;
1450 PNDIS_BUFFER pOrigBuffer;
1451 PUCHAR pMemBuf;
1452 UINT cbBuf = cbPacket + cbHeaderBuffer;
1453 UINT BytesTransferred;
1454
1455 /* allocate NDIS Packet buffer */
1456#ifdef VBOX_NETFLT_ONDEMAND_BIND
1457 /* use the Send packet pool for packet allocation */
1458 NdisAllocatePacket(&Status, &pPacket, pAdapt->hSendPacketPoolHandle);
1459#else
1460 NdisAllocatePacket(&Status, &pPacket, pAdapt->hRecvPacketPoolHandle);
1461#endif
1462 if(Status != NDIS_STATUS_SUCCESS)
1463 {
1464 Assert(0);
1465 break;
1466 }
1467
1468 VBOXNETFLT_OOB_INIT(pPacket);
1469
1470#ifdef VBOX_LOOPBACK_USEFLAGS
1471 /* set "don't loopback" flags */
1472 NdisSetPacketFlags(pPacket, g_fPacketDontLoopBack);
1473#else
1474 NdisSetPacketFlags(pPacket, 0);
1475#endif
1476
1477 Status = vboxNetFltWinMemAlloc(&pMemBuf, cbBuf);
1478 if(Status != NDIS_STATUS_SUCCESS)
1479 {
1480 Assert(0);
1481 NdisFreePacket(pPacket);
1482 break;
1483 }
1484#ifdef VBOX_NETFLT_ONDEMAND_BIND
1485 /* use the Send buffer pool for buffer allocation */
1486 NdisAllocateBuffer(&Status, &pTransferBuffer, pAdapt->hSendBufferPoolHandle, pMemBuf + cbHeaderBuffer, cbPacket);
1487#else
1488 NdisAllocateBuffer(&Status, &pTransferBuffer, pAdapt->hRecvBufferPoolHandle, pMemBuf + cbHeaderBuffer, cbPacket);
1489#endif
1490 if(Status != NDIS_STATUS_SUCCESS)
1491 {
1492 Assert(0);
1493 Status = NDIS_STATUS_FAILURE;
1494 NdisFreePacket(pPacket);
1495 vboxNetFltWinMemFree(pMemBuf);
1496 break;
1497 }
1498
1499#ifdef VBOX_NETFLT_ONDEMAND_BIND
1500 /* use the Send buffer pool for buffer allocation */
1501 NdisAllocateBuffer(&Status, &pOrigBuffer, pAdapt->hSendBufferPoolHandle, pMemBuf, cbBuf);
1502#else
1503 NdisAllocateBuffer(&Status, &pOrigBuffer, pAdapt->hRecvBufferPoolHandle, pMemBuf, cbBuf);
1504#endif
1505 if(Status != NDIS_STATUS_SUCCESS)
1506 {
1507 Assert(0);
1508 Status = NDIS_STATUS_FAILURE;
1509 NdisFreeBuffer(pTransferBuffer);
1510 NdisFreePacket(pPacket);
1511 vboxNetFltWinMemFree(pMemBuf);
1512 break;
1513 }
1514
1515 NdisChainBufferAtBack(pPacket, pTransferBuffer);
1516
1517 NdisMoveMappedMemory(pMemBuf, pHeaderBuffer, cbHeaderBuffer);
1518
1519#ifndef VBOX_NETFLT_ONDEMAND_BIND
1520 vboxNetFltWinPutPacketToList(&pAdapt->TransferDataList, pPacket, pOrigBuffer);
1521#endif
1522
1523#ifdef DEBUG_NETFLT_RECV_TRANSFERDATA
1524 if(cbPacket == cbLookaheadBuffer)
1525 {
1526 NdisCopyLookaheadData(pMemBuf+cbHeaderBuffer,
1527 pLookaheadBuffer,
1528 cbLookaheadBuffer,
1529 pAdapt->fMacOptions);
1530 }
1531 else
1532#endif
1533 {
1534 Assert(cbPacket > cbLookaheadBuffer);
1535
1536 NdisTransferData(
1537 &Status,
1538 pAdapt->hBindingHandle,
1539 MacReceiveContext,
1540 0, /* ByteOffset */
1541 cbPacket,
1542 pPacket,
1543 &BytesTransferred);
1544 }
1545 if(Status != NDIS_STATUS_PENDING)
1546 {
1547 vboxNetFltWinPtTransferDataComplete(pAdapt, pPacket, Status, BytesTransferred);
1548 }
1549 }
1550 } while(0);
1551
1552 return Status;
1553}
1554
1555
1556/**
1557 * Handle receive data indicated up by the miniport below. We pass
1558 * it along to the protocol above us.
1559 *
1560 * If the miniport below indicates packets, NDIS would more
1561 * likely call us at our ReceivePacket handler. However we
1562 * might be called here in certain situations even though
1563 * the miniport below has indicated a receive packet, e.g.
1564 * if the miniport had set packet status to NDIS_STATUS_RESOURCES.
1565 *
1566 * @param ProtocolBindingContext
1567 * @param MacReceiveContext
1568 * @param pHeaderBuffer
1569 * @param cbHeaderBuffer
1570 * @param pLookAheadBuffer
1571 * @param cbLookAheadBuffer
1572 * @param cbPacket
1573 * @return NDIS_STATUS_SUCCESS if we processed the receive successfully,
1574 * NDIS_STATUS_XXX error code if we discarded it. */
1575static NDIS_STATUS
1576vboxNetFltWinPtReceive(
1577 IN NDIS_HANDLE ProtocolBindingContext,
1578 IN NDIS_HANDLE MacReceiveContext,
1579 IN PVOID pHeaderBuffer,
1580 IN UINT cbHeaderBuffer,
1581 IN PVOID pLookAheadBuffer,
1582 IN UINT cbLookAheadBuffer,
1583 IN UINT cbPacket
1584 )
1585{
1586 PADAPT pAdapt = (PADAPT)ProtocolBindingContext;
1587 NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
1588 PVBOXNETFLTINS pNetFlt = PADAPT_2_PVBOXNETFLTINS(pAdapt);
1589#ifdef VBOX_NETFLT_ONDEMAND_BIND
1590#if 0
1591 uint32_t fFlags;
1592#endif
1593
1594 pNetFltIf = vboxNetFltWinReferenceAdaptNetFltFromAdapt(pAdapt);
1595 if(pNetFltIf)
1596 {
1597 do
1598 {
1599#if 0
1600 pPacket = NdisGetReceivedPacket(pAdapt->hBindingHandle, MacReceiveContext);
1601 if(pPacket)
1602 {
1603# ifdef DEBUG_NETFLT_LOOPBACK
1604# error "implement (see comments in the sources below this #error:)"
1605 /* @todo FIXME no need for the PPACKET_INFO mechanism here;
1606 instead the the NDIS_PACKET.ProtocolReserved + INTERLOCKED_SINGLE_LIST mechanism \
1607 similar to that used in TrasferData handling should be used;
1608 */
1609
1610// if(vboxNetFltWinIsLoopedBackPacket(pAdapt, pPacket))
1611# else
1612 if(vboxNetFltWinIsLoopedBackPacket(pPacket) || cbHeaderBuffer != ETH_HEADER_SIZE)
1613# endif
1614
1615 {
1616// Assert(0);
1617 /* nothing else to do here, just return the packet */
1618// NdisReturnPackets(&pPacket, 1);
1619// break;
1620 }
1621
1622 fFlags = MACS_EQUAL(((PRTNETETHERHDR)pHeaderBuffer)->SrcMac, pNetFltIf->u.s.MacAddr) ?
1623 PACKET_COPY | PACKET_SRC_HOST : PACKET_COPY;
1624 Status = vboxNetFltWinQuEnqueuePacket(pNetFltIf, pPacket, fFlags);
1625 if(Status == NDIS_STATUS_SUCCESS)
1626 {
1627 NdisReturnPackets(&pPacket, 1);
1628 pAdapt = NULL;
1629 pNetFltIf = NULL;
1630 break;
1631 }
1632 }
1633#endif
1634 Status = vboxNetFltWinPtReceiveActive(pAdapt, MacReceiveContext, pHeaderBuffer, cbHeaderBuffer,
1635 pLookAheadBuffer, cbLookAheadBuffer, cbPacket);
1636 if(NT_SUCCESS(Status))
1637 {
1638 if(Status != NDIS_STATUS_NOT_ACCEPTED)
1639 {
1640 pAdapt = NULL;
1641 pNetFltIf = NULL;
1642 }
1643 else
1644 {
1645 /* this is a looopback packet, nothing to do here */
1646 }
1647 break;
1648 }
1649 } while(0);
1650
1651 if(pNetFltIf)
1652 vboxNetFltWinDereferenceNetFlt(pNetFltIf);
1653 if(pAdapt)
1654 vboxNetFltWinDereferenceAdapt(pAdapt);
1655
1656
1657#if 0
1658 if(pPacket)
1659 {
1660 NdisReturnPackets(&pPacket, 1);
1661 }
1662#endif
1663 /* we are here because the vboxNetFltWinPtReceiveActive returned pending,
1664 * which means our ProtocolDataTransferComplete we will called,
1665 * so return SUCCESS instead of NOT_ACCEPTED ?? */
1666// return NDIS_STATUS_SUCCESS;
1667 }
1668 return NDIS_STATUS_NOT_ACCEPTED;
1669#else /* if NOT defined VBOX_NETFLT_ONDEMAND_BIND */
1670 PNDIS_PACKET pPacket = NULL;
1671 bool bNetFltActive;
1672 bool fAdaptActive = vboxNetFltWinReferenceAdaptNetFlt(pNetFlt, pAdapt, &bNetFltActive);
1673 const bool bPassThruActive = !bNetFltActive;
1674 if(fAdaptActive)
1675 {
1676 do
1677 {
1678#ifndef DEBUG_NETFLT_RECV_NOPACKET
1679 /*
1680 * Get at the packet, if any, indicated up by the miniport below.
1681 */
1682 pPacket = NdisGetReceivedPacket(pAdapt->hBindingHandle, MacReceiveContext);
1683 if (pPacket != NULL)
1684 {
1685#ifndef VBOX_LOOPBACK_USEFLAGS
1686 PNDIS_PACKET pLb = NULL;
1687#endif
1688 do
1689 {
1690#ifdef VBOX_LOOPBACK_USEFLAGS
1691 if(vboxNetFltWinIsLoopedBackPacket(pPacket))
1692 {
1693 Assert(0);
1694 /* nothing else to do here, just return the packet */
1695 //NdisReturnPackets(&pPacket, 1);
1696 Status = NDIS_STATUS_NOT_ACCEPTED;
1697 break;
1698 }
1699
1700 VBOXNETFLT_LBVERIFY(pNetFlt, pPacket);
1701#endif
1702 if(bNetFltActive)
1703 {
1704#ifndef VBOX_LOOPBACK_USEFLAGS
1705 pLb = vboxNetFltWinLbSearchLoopBack(pAdapt, pPacket, false);
1706 if(!pLb)
1707#endif
1708 {
1709 VBOXNETFLT_LBVERIFY(pNetFlt, pPacket);
1710
1711#ifdef VBOXNETFLT_NO_PACKET_QUEUE
1712 if (vboxNetFltWinPostIntnet(pNetFlt, pPacket, 0))
1713 {
1714 /* drop it */
1715 break;
1716 }
1717#else
1718 Status = vboxNetFltWinQuEnqueuePacket(pNetFlt, pPacket, PACKET_COPY);
1719 Assert(Status == NDIS_STATUS_SUCCESS);
1720 if(Status == NDIS_STATUS_SUCCESS)
1721 {
1722 //NdisReturnPackets(&pPacket, 1);
1723 fAdaptActive = false;
1724 bNetFltActive = false;
1725 break;
1726 }
1727#endif
1728 }
1729#ifndef VBOX_LOOPBACK_USEFLAGS
1730 else if(vboxNetFltWinLbIsFromIntNet(pLb))
1731 {
1732 /* nothing else to do here, just return the packet */
1733 //NdisReturnPackets(&pPacket, 1);
1734 Status = NDIS_STATUS_NOT_ACCEPTED;
1735 break;
1736 }
1737 /* we are here because this is a looped back packet set not from intnet
1738 * we will post it to the upper protocol */
1739#endif
1740 }
1741
1742#ifndef VBOX_LOOPBACK_USEFLAGS
1743 Assert(!pLb || !vboxNetFltWinLbIsFromIntNet(pLb));
1744#endif
1745 Status = vboxNetFltWinRecvPassThru(pAdapt, pPacket);
1746 /* we are done with packet processing, and we will
1747 * not receive packet return event for this packet,
1748 * fAdaptActive should be true to ensure we release adapt*/
1749 Assert(fAdaptActive);
1750 } while(FALSE);
1751
1752#ifdef VBOXNETFLT_NO_PACKET_QUEUE
1753 if(Status == NDIS_STATUS_SUCCESS || Status == NDIS_STATUS_NOT_ACCEPTED
1754# ifndef VBOX_LOOPBACK_USEFLAGS
1755 || pLb
1756# endif
1757 )
1758#endif
1759 {
1760 break;
1761 }
1762 }
1763#endif
1764 if(bNetFltActive)
1765 {
1766 Status = vboxNetFltWinPtReceiveActive(pAdapt, MacReceiveContext, pHeaderBuffer, cbHeaderBuffer,
1767 pLookAheadBuffer, cbLookAheadBuffer, cbPacket);
1768 if(NT_SUCCESS(Status))
1769 {
1770 if(Status != NDIS_STATUS_NOT_ACCEPTED)
1771 {
1772 fAdaptActive = false;
1773 bNetFltActive = false;
1774 }
1775 else
1776 {
1777#ifndef VBOX_LOOPBACK_USEFLAGS
1778 /* this is a loopback packet, nothing to do here */
1779#else
1780 Assert(0);
1781 /* should not be here */
1782#endif
1783 }
1784 break;
1785 }
1786 }
1787
1788 /* Fall through if the miniport below us has either not
1789 * indicated a packet or we could not allocate one */
1790 if(pPacket != NULL)
1791 {
1792 /*
1793 * We are here because we failed to allocate packet
1794 */
1795 vboxNetFltWinPtFlushReceiveQueue(pAdapt, false);
1796 }
1797
1798 /* we are done with packet processing, and we will
1799 * not receive packet return event for this packet,
1800 * fAdaptActive should be true to ensure we release adapt*/
1801 Assert(fAdaptActive);
1802
1803 pAdapt->bIndicateRcvComplete = TRUE;
1804 switch (pAdapt->Medium)
1805 {
1806 case NdisMedium802_3:
1807 case NdisMediumWan:
1808 NdisMEthIndicateReceive(pAdapt->hMiniportHandle,
1809 MacReceiveContext,
1810 (PCHAR)pHeaderBuffer,
1811 cbHeaderBuffer,
1812 pLookAheadBuffer,
1813 cbLookAheadBuffer,
1814 cbPacket);
1815 break;
1816 default:
1817 Assert(FALSE);
1818 break;
1819 }
1820 } while(0);
1821
1822 if(bNetFltActive)
1823 {
1824 vboxNetFltWinDereferenceNetFlt(pNetFlt);
1825 }
1826 else if(bPassThruActive)
1827 {
1828 vboxNetFltWinDereferenceModePassThru(pNetFlt);
1829 }
1830 if(fAdaptActive)
1831 {
1832 vboxNetFltWinDereferenceAdapt(pAdapt);
1833 }
1834 }
1835 else
1836 {
1837 Status = NDIS_STATUS_FAILURE;
1838 }
1839
1840 return Status;
1841#endif
1842}
1843
1844/**
1845 * Called by the adapter below us when it is done indicating a batch of
1846 * received packets.
1847 *
1848 * @param ProtocolBindingContext Pointer to our adapter structure.
1849 * @return None */
1850static VOID
1851vboxNetFltWinPtReceiveComplete(
1852 IN NDIS_HANDLE ProtocolBindingContext
1853 )
1854{
1855#ifndef VBOX_NETFLT_ONDEMAND_BIND
1856 PADAPT pAdapt =(PADAPT)ProtocolBindingContext;
1857 PVBOXNETFLTINS pNetFlt = PADAPT_2_PVBOXNETFLTINS(pAdapt);
1858 ULONG NumberOfPackets = 0;
1859 /* since the receive array queued packets do not hold the reference we need to
1860 * reference the PassThru/NetFlt mode here to avoid packet reordering caused by
1861 * concurrently running vboxNetFltWinPtReceiveComplete and vboxNetFltPortOsSetActive
1862 * on netflt activation/deactivation */
1863 bool bNetFltActive;
1864 bool fAdaptActive = vboxNetFltWinReferenceAdaptNetFlt(pNetFlt, pAdapt, &bNetFltActive);
1865
1866 vboxNetFltWinPtFlushReceiveQueue(pAdapt, false);
1867
1868 if ((pAdapt->hMiniportHandle != NULL)
1869 /* && (pAdapt->MPDeviceState == NdisDeviceStateD0) */
1870 && (pAdapt->bIndicateRcvComplete == TRUE))
1871 {
1872 switch (pAdapt->Medium)
1873 {
1874 case NdisMedium802_3:
1875 case NdisMediumWan:
1876 NdisMEthIndicateReceiveComplete(pAdapt->hMiniportHandle);
1877 break;
1878 default:
1879 Assert(FALSE);
1880 break;
1881 }
1882 }
1883
1884 pAdapt->bIndicateRcvComplete = FALSE;
1885
1886 if(fAdaptActive)
1887 {
1888 if(bNetFltActive)
1889 {
1890 vboxNetFltWinDereferenceNetFlt(pNetFlt);
1891 }
1892 else
1893 {
1894 vboxNetFltWinDereferenceModePassThru(pNetFlt);
1895 }
1896 vboxNetFltWinDereferenceAdapt(pAdapt);
1897 }
1898#endif
1899}
1900
1901/**
1902 * ReceivePacket handler. Called by NDIS if the miniport below supports
1903 * NDIS 4.0 style receives. Re-package the buffer chain in a new packet
1904 * and indicate the new packet to protocols above us. Any context for
1905 * packets indicated up must be kept in the MiniportReserved field.
1906 *
1907 * @param ProtocolBindingContext - Pointer to our adapter structure.
1908 * @param Packet - Pointer to the packet
1909 * @return == 0 -> We are done with the packet,
1910 * != 0 -> We will keep the packet and call NdisReturnPackets() this many times when done.
1911 */
1912static INT
1913vboxNetFltWinPtReceivePacket(
1914 IN NDIS_HANDLE ProtocolBindingContext,
1915 IN PNDIS_PACKET pPacket
1916 )
1917{
1918 PADAPT pAdapt =(PADAPT)ProtocolBindingContext;
1919 INT cRefCount = 0;
1920 PVBOXNETFLTINS pNetFlt = PADAPT_2_PVBOXNETFLTINS(pAdapt);
1921#ifdef VBOX_NETFLT_ONDEMAND_BIND
1922 PNDIS_BUFFER pBuffer;
1923 PVOID pVA;
1924 UINT cbLength;
1925 uint32_t fFlags;
1926
1927 pNetFltIf = vboxNetFltWinReferenceAdaptNetFltFromAdapt(pAdapt);
1928
1929 if(pNetFltIf)
1930 {
1931 NDIS_STATUS Status;
1932 bool bResources;
1933 do
1934 {
1935#ifdef DEBUG_NETFLT_LOOPBACK
1936# error "implement (see comments in the sources below this #error:)"
1937 /* @todo FIXME no need for the PPACKET_INFO mechanism here;
1938 instead the the NDIS_PACKET.ProtocolReserved + INTERLOCKED_SINGLE_LIST mechanism \
1939 similar to that used in TrasferData handling should be used;
1940 */
1941
1942// if(vboxNetFltWinIsLoopedBackPacket(pAdapt, pPacket))
1943#else
1944 if(vboxNetFltWinIsLoopedBackPacket(pPacket))
1945#endif
1946
1947 {
1948 Assert(0);
1949 NdisReturnPackets(&pPacket, 1);
1950 break;
1951 }
1952 bResources = NDIS_GET_PACKET_STATUS(pPacket) == NDIS_STATUS_RESOURCES;
1953
1954 NdisQueryPacket(pPacket, NULL, NULL, &pBuffer, NULL);
1955 if(!pBuffer)
1956 {
1957 Assert(0);
1958 NdisReturnPackets(&pPacket, 1);
1959 cRefCount = 0;
1960 break;
1961 }
1962
1963 NdisQueryBufferSafe(pBuffer, &pVA, &cbLength, NormalPagePriority);
1964 if(!pVA || !cbLength)
1965 {
1966 Assert(0);
1967 NdisReturnPackets(&pPacket, 1);
1968 cRefCount = 0;
1969 break;
1970 }
1971
1972 fFlags = MACS_EQUAL(((PRTNETETHERHDR)pVA)->SrcMac, pNetFltIf->u.s.MacAddr) ? PACKET_SRC_HOST : 0;
1973
1974 Status = vboxNetFltWinQuEnqueuePacket(pNetFltIf, pPacket, bResources ? fFlags | PACKET_COPY : fFlags);
1975 if(Status == NDIS_STATUS_SUCCESS)
1976 {
1977 if(bResources)
1978 {
1979 cRefCount = 0;
1980 NdisReturnPackets(&pPacket, 1);
1981 }
1982 else
1983 {
1984 cRefCount = 1;
1985 }
1986 pNetFltIf = NULL;
1987 pAdapt = NULL;
1988 break;
1989 }
1990 else
1991 {
1992 Assert(0);
1993 NdisReturnPackets(&pPacket, 1);
1994 cRefCount = 0;
1995 break;
1996 }
1997 } while (0);
1998
1999 if(pNetFltIf)
2000 vboxNetFltWinDereferenceNetFlt(pNetFltIf);
2001 if(pAdapt)
2002 vboxNetFltWinDereferenceAdapt(pAdapt);
2003 return cRefCount;
2004 }
2005 /* we are here because we are inactive, simply return the packet */
2006 NdisReturnPackets(&pPacket, 1);
2007 return 0;
2008#else
2009 bool bNetFltActive;
2010 bool fAdaptActive = vboxNetFltWinReferenceAdaptNetFlt(pNetFlt, pAdapt, &bNetFltActive);
2011 const bool bPassThruActive = !bNetFltActive;
2012 if(fAdaptActive)
2013 {
2014 do
2015 {
2016#ifdef VBOX_LOOPBACK_USEFLAGS
2017 if(vboxNetFltWinIsLoopedBackPacket(pPacket))
2018 {
2019 Assert(0);
2020 Log(("lb_rp"));
2021
2022 /* nothing else to do here, just return the packet */
2023 cRefCount = 0;
2024 //NdisReturnPackets(&pPacket, 1);
2025 break;
2026 }
2027
2028 VBOXNETFLT_LBVERIFY(pNetFlt, pPacket);
2029#endif
2030
2031 if(bNetFltActive)
2032 {
2033#ifndef VBOX_LOOPBACK_USEFLAGS
2034 PNDIS_PACKET pLb = vboxNetFltWinLbSearchLoopBack(pAdapt, pPacket, false);
2035 if(!pLb)
2036#endif
2037 {
2038#ifndef VBOXNETFLT_NO_PACKET_QUEUE
2039 NDIS_STATUS fStatus;
2040#endif
2041 bool bResources = NDIS_GET_PACKET_STATUS(pPacket) == NDIS_STATUS_RESOURCES;
2042
2043 VBOXNETFLT_LBVERIFY(pNetFlt, pPacket);
2044
2045 /*TODO: remove this assert.
2046 * this is a temporary assert for debugging purposes:
2047 * we're probably doing something wrong with the packets if the miniport reports NDIS_STATUS_RESOURCES */
2048 Assert(!bResources);
2049
2050#ifdef VBOXNETFLT_NO_PACKET_QUEUE
2051 if (vboxNetFltWinPostIntnet(pNetFlt, pPacket, 0))
2052 {
2053 /* drop it */
2054 cRefCount = 0;
2055 break;
2056 }
2057
2058#else
2059 fStatus = vboxNetFltWinQuEnqueuePacket(pNetFlt, pPacket, bResources ? PACKET_COPY : 0);
2060 if(fStatus == NDIS_STATUS_SUCCESS)
2061 {
2062 bNetFltActive = false;
2063 fAdaptActive = false;
2064 if(bResources)
2065 {
2066 cRefCount = 0;
2067 //NdisReturnPackets(&pPacket, 1);
2068 }
2069 else
2070 {
2071 cRefCount = 1;
2072 }
2073 break;
2074 }
2075 else
2076 {
2077 Assert(0);
2078 }
2079#endif
2080 }
2081#ifndef VBOX_LOOPBACK_USEFLAGS
2082 else if(vboxNetFltWinLbIsFromIntNet(pLb))
2083 {
2084 /* the packet is from intnet, it has already been set to the host,
2085 * no need for loopng it back to the host again */
2086 /* nothing else to do here, just return the packet */
2087 cRefCount = 0;
2088 //NdisReturnPackets(&pPacket, 1);
2089 break;
2090 }
2091#endif
2092 }
2093
2094 cRefCount = vboxNetFltWinRecvPacketPassThru(pAdapt, pPacket);
2095 if(cRefCount)
2096 {
2097 Assert(cRefCount == 1);
2098 fAdaptActive = false;
2099 }
2100
2101 } while(FALSE);
2102
2103 if(bNetFltActive)
2104 {
2105 vboxNetFltWinDereferenceNetFlt(pNetFlt);
2106 }
2107 else if(bPassThruActive)
2108 {
2109 vboxNetFltWinDereferenceModePassThru(pNetFlt);
2110 }
2111 if(fAdaptActive)
2112 {
2113 vboxNetFltWinDereferenceAdapt(pAdapt);
2114 }
2115 }
2116 else
2117 {
2118 cRefCount = 0;
2119 //NdisReturnPackets(&pPacket, 1);
2120 }
2121
2122 return cRefCount;
2123#endif
2124}
2125
2126/**
2127 * This routine is called from NDIS to notify our protocol edge of a
2128 * reconfiguration of parameters for either a specific binding (pAdapt
2129 * is not NULL), or global parameters if any (pAdapt is NULL).
2130 *
2131 * @param pAdapt - Pointer to our adapter structure.
2132 * @param pNetPnPEvent - the reconfigure event
2133 * @return NDIS_STATUS_SUCCESS */
2134static NDIS_STATUS
2135vboxNetFltWinPtPnPNetEventReconfigure(
2136 IN PADAPT pAdapt,
2137 IN PNET_PNP_EVENT pNetPnPEvent
2138 )
2139{
2140 NDIS_STATUS ReconfigStatus = NDIS_STATUS_SUCCESS;
2141 NDIS_STATUS ReturnStatus = NDIS_STATUS_SUCCESS;
2142
2143 do
2144 {
2145 /*
2146 * Is this is a global reconfiguration notification ?
2147 */
2148 if (pAdapt == NULL)
2149 {
2150 /*
2151 * An important event that causes this notification to us is if
2152 * one of our upper-edge miniport instances was enabled after being
2153 * disabled earlier, e.g. from Device Manager in Win2000. Note that
2154 * NDIS calls this because we had set up an association between our
2155 * miniport and protocol entities by calling NdisIMAssociateMiniport.
2156 *
2157 * Since we would have torn down the lower binding for that miniport,
2158 * we need NDIS' assistance to re-bind to the lower miniport. The
2159 * call to NdisReEnumerateProtocolBindings does exactly that.
2160 */
2161 NdisReEnumerateProtocolBindings (g_hProtHandle);
2162 break;
2163 }
2164
2165 ReconfigStatus = NDIS_STATUS_SUCCESS;
2166
2167 } while(FALSE);
2168
2169 LogFlow(("<==PtPNPNetEventReconfigure: pAdapt %p\n", pAdapt));
2170
2171 return ReconfigStatus;
2172}
2173
2174static NDIS_STATUS
2175vboxNetFltWinPtPnPNetEventBindsComplete(
2176 IN PADAPT pAdapt,
2177 IN PNET_PNP_EVENT pNetPnPEvent
2178 )
2179{
2180 return NDIS_STATUS_SUCCESS;
2181}
2182
2183DECLHIDDEN(bool) vboxNetFltWinPtCloseAdapter(PADAPT pAdapt, PNDIS_STATUS pStatus)
2184{
2185 PVBOXNETFLTINS pNetFlt = PADAPT_2_PVBOXNETFLTINS(pAdapt);
2186 RTSPINLOCKTMP Tmp = RTSPINLOCKTMP_INITIALIZER;
2187
2188 RTSpinlockAcquireNoInts(pNetFlt->hSpinlock, &Tmp);
2189
2190 if(pAdapt->bClosingAdapter)
2191 {
2192 RTSpinlockReleaseNoInts(pNetFlt->hSpinlock, &Tmp);
2193 Assert(0);
2194 return false;
2195 }
2196 if (pAdapt->hBindingHandle == NULL)
2197 {
2198 RTSpinlockReleaseNoInts(pNetFlt->hSpinlock, &Tmp);
2199 Assert(0);
2200 return false;
2201 }
2202
2203 pAdapt->bClosingAdapter = true;
2204 RTSpinlockReleaseNoInts(pNetFlt->hSpinlock, &Tmp);
2205
2206 /*
2207 * Close the binding below. and wait for it to complete
2208 */
2209 NdisResetEvent(&pAdapt->hEvent);
2210
2211 NdisCloseAdapter(pStatus, pAdapt->hBindingHandle);
2212
2213 if (*pStatus == NDIS_STATUS_PENDING)
2214 {
2215 NdisWaitEvent(&pAdapt->hEvent, 0);
2216 *pStatus = pAdapt->Status;
2217 }
2218
2219 Assert (*pStatus == NDIS_STATUS_SUCCESS);
2220
2221 pAdapt->hBindingHandle = NULL;
2222
2223 return true;
2224}
2225
2226/**
2227 * This is a notification to our protocol edge of the power state
2228 * of the lower miniport. If it is going to a low-power state, we must
2229 * wait here for all outstanding sends and requests to complete.
2230 *
2231 * @param pAdapt - Pointer to the adpater structure
2232 * @param pNetPnPEvent - The Net Pnp Event. this contains the new device state
2233 * @return NDIS_STATUS_SUCCESS or the status returned by upper-layer protocols.
2234 * */
2235static NDIS_STATUS
2236vboxNetFltWinPtPnPNetEventSetPower(
2237 IN PADAPT pAdapt,
2238 IN PNET_PNP_EVENT pNetPnPEvent
2239 )
2240{
2241 PNDIS_DEVICE_POWER_STATE pDeviceState =(PNDIS_DEVICE_POWER_STATE)(pNetPnPEvent->Buffer);
2242 NDIS_DEVICE_POWER_STATE PrevDeviceState = vboxNetFltWinGetPowerState(&pAdapt->PTState);
2243 NDIS_STATUS ReturnStatus;
2244 PVBOXNETFLTINS pNetFlt = PADAPT_2_PVBOXNETFLTINS(pAdapt);
2245 RTSPINLOCKTMP Tmp = RTSPINLOCKTMP_INITIALIZER;
2246 int cPPUsage;
2247
2248 ReturnStatus = NDIS_STATUS_SUCCESS;
2249
2250 /*
2251 * Set the Internal Device State, this blocks all new sends or receives
2252 */
2253 RTSpinlockAcquireNoInts(pNetFlt->hSpinlock, &Tmp);
2254
2255 vboxNetFltWinSetPowerState(&pAdapt->PTState, *pDeviceState);
2256
2257 /*
2258 * Check if the miniport below is going to a low power state.
2259 */
2260 if (vboxNetFltWinGetPowerState(&pAdapt->PTState) > NdisDeviceStateD0)
2261 {
2262 /*
2263 * If the miniport below is going to standby, fail all incoming requests
2264 */
2265 if (PrevDeviceState == NdisDeviceStateD0)
2266 {
2267 pAdapt->bStandingBy = TRUE;
2268 }
2269 RTSpinlockReleaseNoInts(pNetFlt->hSpinlock, &Tmp);
2270#ifndef VBOX_NETFLT_ONDEMAND_BIND
2271
2272 vboxNetFltWinPtFlushReceiveQueue(pAdapt, false);
2273
2274 vboxNetFltWinWaitDereference(&pAdapt->MPState);
2275#endif
2276
2277 /*
2278 * Wait for outstanding sends and requests to complete.
2279 */
2280 vboxNetFltWinWaitDereference(&pAdapt->PTState);
2281
2282#ifndef VBOX_NETFLT_ONDEMAND_BIND
2283 while (ASMAtomicUoReadBool((volatile bool *)&pAdapt->bOutstandingRequests))
2284 {
2285 /*
2286 * sleep till outstanding requests complete
2287 */
2288 vboxNetFltWinSleep(2);
2289 }
2290
2291 /*
2292 * If the below miniport is going to low power state, complete the queued request
2293 */
2294 RTSpinlockAcquireNoInts(pNetFlt->hSpinlock, &Tmp);
2295 if (pAdapt->bQueuedRequest)
2296 {
2297 pAdapt->bQueuedRequest = FALSE;
2298 RTSpinlockReleaseNoInts(pNetFlt->hSpinlock, &Tmp);
2299 vboxNetFltWinPtRequestComplete(pAdapt, &pAdapt->Request, NDIS_STATUS_FAILURE);
2300 }
2301 else
2302 {
2303 RTSpinlockReleaseNoInts(pNetFlt->hSpinlock, &Tmp);
2304 }
2305#endif
2306
2307 /* check packet pool is empty */
2308 cPPUsage = NdisPacketPoolUsage(pAdapt->hSendPacketPoolHandle);
2309 Assert(cPPUsage == 0);
2310 cPPUsage = NdisPacketPoolUsage(pAdapt->hRecvPacketPoolHandle);
2311 Assert(cPPUsage == 0);
2312 /* for debugging only, ignore the err in release */
2313 NOREF(cPPUsage);
2314
2315#ifndef VBOX_NETFLT_ONDEMAND_BIND
2316 Assert(pAdapt->bOutstandingRequests == FALSE);
2317#endif
2318 }
2319 else
2320 {
2321 /*
2322 * If the physical miniport is powering up (from Low power state to D0),
2323 * clear the flag
2324 */
2325 if (PrevDeviceState > NdisDeviceStateD0)
2326 {
2327 pAdapt->bStandingBy = FALSE;
2328 }
2329
2330#ifdef VBOX_NETFLT_ONDEMAND_BIND
2331 RTSpinlockReleaseNoInts(pNetFlt->hSpinlock, &Tmp);
2332#else
2333 /*
2334 * The device below is being turned on. If we had a request
2335 * pending, send it down now.
2336 */
2337 if (pAdapt->bQueuedRequest == TRUE)
2338 {
2339 NDIS_STATUS Status;
2340
2341 pAdapt->bQueuedRequest = FALSE;
2342
2343 pAdapt->bOutstandingRequests = TRUE;
2344 RTSpinlockReleaseNoInts(pNetFlt->hSpinlock, &Tmp);
2345
2346 NdisRequest(&Status,
2347 pAdapt->hBindingHandle,
2348 &pAdapt->Request);
2349
2350 if (Status != NDIS_STATUS_PENDING)
2351 {
2352 vboxNetFltWinPtRequestComplete(pAdapt,
2353 &pAdapt->Request,
2354 Status);
2355
2356 }
2357 }
2358 else
2359 {
2360 RTSpinlockReleaseNoInts(pNetFlt->hSpinlock, &Tmp);
2361 }
2362
2363#endif /* #ifndef VBOX_NETFLT_ONDEMAND_BIND */
2364
2365 }
2366
2367 return ReturnStatus;
2368}
2369
2370/**
2371 * This is called by NDIS to notify us of a PNP event related to a lower
2372 * binding. Based on the event, this dispatches to other helper routines.
2373 *
2374 * @param ProtocolBindingContext - Pointer to our adapter structure. Can be NULL
2375 * for "global" notifications
2376 * @param pNetPnPEvent - Pointer to the PNP event to be processed.
2377 * @return NDIS_STATUS code indicating status of event processing.
2378 * */
2379static NDIS_STATUS
2380vboxNetFltWinPtPnPHandler(
2381 IN NDIS_HANDLE ProtocolBindingContext,
2382 IN PNET_PNP_EVENT pNetPnPEvent
2383 )
2384{
2385 PADAPT pAdapt =(PADAPT)ProtocolBindingContext;
2386 NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
2387
2388 LogFlow(("vboxNetFltWinPtPnPHandler: Adapt %p, Event %d\n", pAdapt, pNetPnPEvent->NetEvent));
2389
2390 switch (pNetPnPEvent->NetEvent)
2391 {
2392 case NetEventSetPower:
2393 Status = vboxNetFltWinPtPnPNetEventSetPower(pAdapt, pNetPnPEvent);
2394 break;
2395
2396 case NetEventReconfigure:
2397 DBGPRINT(("NetEventReconfigure, pAdapt(%p)", pAdapt));
2398 Status = vboxNetFltWinPtPnPNetEventReconfigure(pAdapt, pNetPnPEvent);
2399 break;
2400 case NetEventBindsComplete:
2401 DBGPRINT(("NetEventBindsComplete"));
2402 Status = vboxNetFltWinPtPnPNetEventBindsComplete(pAdapt, pNetPnPEvent);
2403 break;
2404 default:
2405 Status = NDIS_STATUS_SUCCESS;
2406 break;
2407 }
2408
2409 return Status;
2410}
2411#ifdef __cplusplus
2412# define PTCHARS_40(_p) ((_p).Ndis40Chars)
2413#else
2414# define PTCHARS_40(_p) (_p)
2415#endif
2416
2417/**
2418 * register the protocol edge
2419 */
2420DECLHIDDEN(NDIS_STATUS)
2421vboxNetFltWinPtRegister(
2422 IN PDRIVER_OBJECT DriverObject,
2423 IN PUNICODE_STRING RegistryPath
2424 )
2425{
2426 NDIS_STATUS Status;
2427 NDIS_PROTOCOL_CHARACTERISTICS PChars;
2428 NDIS_STRING Name;
2429
2430 /*
2431 * Now register the protocol.
2432 */
2433 NdisZeroMemory(&PChars, sizeof(NDIS_PROTOCOL_CHARACTERISTICS));
2434 PTCHARS_40(PChars).MajorNdisVersion = VBOXNETFLT_PROT_MAJOR_NDIS_VERSION;
2435 PTCHARS_40(PChars).MinorNdisVersion = VBOXNETFLT_PROT_MINOR_NDIS_VERSION;
2436
2437 /*
2438 * Make sure the protocol-name matches the service-name
2439 * (from the INF) under which this protocol is installed.
2440 * This is needed to ensure that NDIS can correctly determine
2441 * the binding and call us to bind to miniports below.
2442 */
2443 NdisInitUnicodeString(&Name, VBOXNETFLT_PROTOCOL_NAME); /* Protocol name */
2444 PTCHARS_40(PChars).Name = Name;
2445 PTCHARS_40(PChars).OpenAdapterCompleteHandler = vboxNetFltWinPtOpenAdapterComplete;
2446 PTCHARS_40(PChars).CloseAdapterCompleteHandler = vboxNetFltWinPtCloseAdapterComplete;
2447 PTCHARS_40(PChars).SendCompleteHandler = vboxNetFltWinPtSendComplete;
2448 PTCHARS_40(PChars).TransferDataCompleteHandler = vboxNetFltWinPtTransferDataComplete;
2449
2450 PTCHARS_40(PChars).ResetCompleteHandler = vboxNetFltWinPtResetComplete;
2451 PTCHARS_40(PChars).RequestCompleteHandler = vboxNetFltWinPtRequestComplete;
2452 PTCHARS_40(PChars).ReceiveHandler = vboxNetFltWinPtReceive;
2453 PTCHARS_40(PChars).ReceiveCompleteHandler = vboxNetFltWinPtReceiveComplete;
2454 PTCHARS_40(PChars).StatusHandler = vboxNetFltWinPtStatus;
2455 PTCHARS_40(PChars).StatusCompleteHandler = vboxNetFltWinPtStatusComplete;
2456 PTCHARS_40(PChars).BindAdapterHandler = vboxNetFltWinPtBindAdapter;
2457 PTCHARS_40(PChars).UnbindAdapterHandler = vboxNetFltWinPtUnbindAdapter;
2458 PTCHARS_40(PChars).UnloadHandler = vboxNetFltWinPtUnloadProtocol;
2459#if !defined(VBOX_NETFLT_ONDEMAND_BIND) && !defined(DEBUG_NETFLT_RECV)
2460 PTCHARS_40(PChars).ReceivePacketHandler = vboxNetFltWinPtReceivePacket;
2461#else
2462 PTCHARS_40(PChars).ReceivePacketHandler = NULL;
2463#endif
2464 PTCHARS_40(PChars).PnPEventHandler= vboxNetFltWinPtPnPHandler;
2465
2466 NdisRegisterProtocol(&Status,
2467 &g_hProtHandle,
2468 &PChars,
2469 sizeof(NDIS_PROTOCOL_CHARACTERISTICS));
2470
2471 return Status;
2472}
2473
2474/**
2475 * deregister the protocol edge
2476 */
2477DECLHIDDEN(NDIS_STATUS)
2478vboxNetFltWinPtDeregister()
2479{
2480 NDIS_STATUS Status;
2481
2482 if (g_hProtHandle != NULL)
2483 {
2484 NdisDeregisterProtocol(&Status, g_hProtHandle);
2485 g_hProtHandle = NULL;
2486 }
2487
2488 return Status;
2489}
2490
2491#ifndef VBOX_NETFLT_ONDEMAND_BIND
2492/**
2493 * returns the protocol handle
2494 */
2495DECLHIDDEN(NDIS_HANDLE) vboxNetFltWinPtGetHandle()
2496{
2497 return g_hProtHandle;
2498}
2499#endif
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