VirtualBox

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

Last change on this file since 32740 was 32338, checked in by vboxsync, 14 years ago

NetFlt/win: fix possible stack overflow for loopback handling on heavy network load

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