1 | /* $Id: VBoxNetFltP-win.cpp 36184 2011-03-07 10:57:04Z vboxsync $ */
|
---|
2 | /** @file
|
---|
3 | * VBoxNetFltP-win.cpp - Bridged Networking Driver, Windows Specific Code.
|
---|
4 | * Protocol edge
|
---|
5 | */
|
---|
6 | /*
|
---|
7 | * Copyright (C) 2011 Oracle Corporation
|
---|
8 | *
|
---|
9 | * This file is part of VirtualBox Open Source Edition (OSE), as
|
---|
10 | * available from http://www.virtualbox.org. This file is free software;
|
---|
11 | * you can redistribute it and/or modify it under the terms of the GNU
|
---|
12 | * General Public License (GPL) as published by the Free Software
|
---|
13 | * Foundation, in version 2 as it comes in the "COPYING" file of the
|
---|
14 | * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
|
---|
15 | * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
|
---|
16 | */
|
---|
17 | #include "VBoxNetFltCmn-win.h"
|
---|
18 |
|
---|
19 | #ifdef VBOXNETADP
|
---|
20 | # error "No protocol edge"
|
---|
21 | #endif
|
---|
22 |
|
---|
23 | #define VBOXNETFLT_PT_STATUS_IS_FILTERED(_s) (\
|
---|
24 | (_s) == NDIS_STATUS_MEDIA_CONNECT \
|
---|
25 | || (_s) == NDIS_STATUS_MEDIA_DISCONNECT \
|
---|
26 | )
|
---|
27 |
|
---|
28 | /**
|
---|
29 | * performs binding to the given adapter
|
---|
30 | */
|
---|
31 | DECLHIDDEN(NDIS_STATUS) vboxNetFltWinPtDoBinding(PVBOXNETFLTINS pThis, PNDIS_STRING pOurDeviceName, PNDIS_STRING pBindToDeviceName)
|
---|
32 | {
|
---|
33 | Assert(pThis->u.s.WinIf.PtState.PowerState == NdisDeviceStateD3);
|
---|
34 | Assert(pThis->u.s.WinIf.PtState.OpState == kVBoxNetDevOpState_Deinitialized);
|
---|
35 | Assert(KeGetCurrentIrql() == PASSIVE_LEVEL);
|
---|
36 |
|
---|
37 | vboxNetFltWinSetOpState(&pThis->u.s.WinIf.PtState, kVBoxNetDevOpState_Initializing);
|
---|
38 |
|
---|
39 | NDIS_STATUS Status = vboxNetFltWinCopyString(&pThis->u.s.WinIf.MpDeviceName, pOurDeviceName);
|
---|
40 | Assert (Status == NDIS_STATUS_SUCCESS);
|
---|
41 | if (Status == NDIS_STATUS_SUCCESS)
|
---|
42 | {
|
---|
43 | vboxNetFltWinSetPowerState(&pThis->u.s.WinIf.PtState, NdisDeviceStateD0);
|
---|
44 | pThis->u.s.WinIf.OpenCloseStatus = NDIS_STATUS_SUCCESS;
|
---|
45 |
|
---|
46 | UINT iMedium;
|
---|
47 | NDIS_STATUS TmpStatus;
|
---|
48 | NDIS_MEDIUM aenmNdisMedium[] =
|
---|
49 | {
|
---|
50 | /* Ethernet */
|
---|
51 | NdisMedium802_3,
|
---|
52 | /* Wan */
|
---|
53 | NdisMediumWan
|
---|
54 | };
|
---|
55 |
|
---|
56 | NdisResetEvent(&pThis->u.s.WinIf.OpenCloseEvent);
|
---|
57 |
|
---|
58 | NdisOpenAdapter(&Status, &TmpStatus, &pThis->u.s.WinIf.hBinding, &iMedium,
|
---|
59 | aenmNdisMedium, RT_ELEMENTS(aenmNdisMedium),
|
---|
60 | g_VBoxNetFltGlobalsWin.Pt.hProtocol,
|
---|
61 | pThis,
|
---|
62 | pBindToDeviceName,
|
---|
63 | 0, /* IN UINT OpenOptions, (reserved, should be NULL) */
|
---|
64 | NULL /* IN PSTRING AddressingInformation OPTIONAL */
|
---|
65 | );
|
---|
66 | Assert(Status == NDIS_STATUS_PENDING || Status == STATUS_SUCCESS);
|
---|
67 | if (Status == NDIS_STATUS_PENDING)
|
---|
68 | {
|
---|
69 | NdisWaitEvent(&pThis->u.s.WinIf.OpenCloseEvent, 0);
|
---|
70 | Status = pThis->u.s.WinIf.OpenCloseStatus;
|
---|
71 | }
|
---|
72 |
|
---|
73 | Assert(Status == NDIS_STATUS_SUCCESS);
|
---|
74 | if (Status == NDIS_STATUS_SUCCESS)
|
---|
75 | {
|
---|
76 | Assert(pThis->u.s.WinIf.hBinding);
|
---|
77 | pThis->u.s.WinIf.enmMedium = aenmNdisMedium[iMedium];
|
---|
78 | vboxNetFltWinSetOpState(&pThis->u.s.WinIf.PtState, kVBoxNetDevOpState_Initialized);
|
---|
79 |
|
---|
80 | Status = vboxNetFltWinMpInitializeDevideInstance(pThis);
|
---|
81 | Assert(Status == NDIS_STATUS_SUCCESS);
|
---|
82 | if (Status == NDIS_STATUS_SUCCESS)
|
---|
83 | {
|
---|
84 | return NDIS_STATUS_SUCCESS;
|
---|
85 | }
|
---|
86 | else
|
---|
87 | {
|
---|
88 | LogRel((__FUNCTION__": vboxNetFltWinMpInitializeDevideInstance failed, Status 0x%x\n", Status));
|
---|
89 | }
|
---|
90 |
|
---|
91 | vboxNetFltWinSetOpState(&pThis->u.s.WinIf.PtState, kVBoxNetDevOpState_Deinitializing);
|
---|
92 | vboxNetFltWinPtCloseInterface(pThis, &TmpStatus);
|
---|
93 | Assert(TmpStatus == NDIS_STATUS_SUCCESS);
|
---|
94 | vboxNetFltWinSetOpState(&pThis->u.s.WinIf.PtState, kVBoxNetDevOpState_Deinitialized);
|
---|
95 | }
|
---|
96 | else
|
---|
97 | {
|
---|
98 | LogRel((__FUNCTION__"NdisOpenAdapter failed, Status (0x%x)", Status));
|
---|
99 | }
|
---|
100 |
|
---|
101 | vboxNetFltWinSetOpState(&pThis->u.s.WinIf.PtState, kVBoxNetDevOpState_Deinitialized);
|
---|
102 | pThis->u.s.WinIf.hBinding = NULL;
|
---|
103 | }
|
---|
104 |
|
---|
105 | return Status;
|
---|
106 | }
|
---|
107 |
|
---|
108 | static VOID vboxNetFltWinPtBindAdapter(OUT PNDIS_STATUS pStatus,
|
---|
109 | IN NDIS_HANDLE hBindContext,
|
---|
110 | IN PNDIS_STRING pDeviceNameStr,
|
---|
111 | IN PVOID pvSystemSpecific1,
|
---|
112 | IN PVOID pvSystemSpecific2)
|
---|
113 | {
|
---|
114 | LogFlow(("==>"__FUNCTION__"\n"));
|
---|
115 |
|
---|
116 | NDIS_STATUS Status;
|
---|
117 | NDIS_HANDLE hConfig = NULL;
|
---|
118 |
|
---|
119 | NdisOpenProtocolConfiguration(&Status, &hConfig, (PNDIS_STRING)pvSystemSpecific1);
|
---|
120 | Assert(Status == NDIS_STATUS_SUCCESS);
|
---|
121 | if (Status == NDIS_STATUS_SUCCESS)
|
---|
122 | {
|
---|
123 | PNDIS_CONFIGURATION_PARAMETER pParam;
|
---|
124 | NDIS_STRING UppedBindStr = NDIS_STRING_CONST("UpperBindings");
|
---|
125 | NdisReadConfiguration(&Status, &pParam, hConfig, &UppedBindStr, NdisParameterString);
|
---|
126 | Assert(Status == NDIS_STATUS_SUCCESS);
|
---|
127 | if (Status == NDIS_STATUS_SUCCESS)
|
---|
128 | {
|
---|
129 | PVBOXNETFLTINS pNetFlt;
|
---|
130 | Status = vboxNetFltWinPtInitBind(&pNetFlt, &pParam->ParameterData.StringData, pDeviceNameStr);
|
---|
131 | Assert(Status == NDIS_STATUS_SUCCESS);
|
---|
132 | }
|
---|
133 |
|
---|
134 | NdisCloseConfiguration(hConfig);
|
---|
135 | }
|
---|
136 |
|
---|
137 | *pStatus = Status;
|
---|
138 |
|
---|
139 | LogFlow(("<=="__FUNCTION__": Status 0x%x\n", Status));
|
---|
140 | }
|
---|
141 |
|
---|
142 | static VOID vboxNetFltWinPtOpenAdapterComplete(IN NDIS_HANDLE hProtocolBindingContext, IN NDIS_STATUS Status, IN NDIS_STATUS OpenErrorStatus)
|
---|
143 | {
|
---|
144 | PVBOXNETFLTINS pNetFlt =(PVBOXNETFLTINS)hProtocolBindingContext;
|
---|
145 |
|
---|
146 | LogFlow(("==>"__FUNCTION__": pNetFlt (0x%p), Status (0x%x), OpenErrorStatus(0x%x)\n", pNetFlt, Status, OpenErrorStatus));
|
---|
147 | Assert(pNetFlt->u.s.WinIf.OpenCloseStatus == NDIS_STATUS_SUCCESS);
|
---|
148 | Assert(Status == NDIS_STATUS_SUCCESS);
|
---|
149 | if (pNetFlt->u.s.WinIf.OpenCloseStatus == NDIS_STATUS_SUCCESS)
|
---|
150 | {
|
---|
151 | pNetFlt->u.s.WinIf.OpenCloseStatus = Status;
|
---|
152 | Assert(Status == NDIS_STATUS_SUCCESS);
|
---|
153 | if (Status != NDIS_STATUS_SUCCESS)
|
---|
154 | LogRel((__FUNCTION__" : Open Complete status is 0x%x", Status));
|
---|
155 | }
|
---|
156 | else
|
---|
157 | LogRel((__FUNCTION__" : Adapter maintained status is 0x%x", pNetFlt->u.s.WinIf.OpenCloseStatus));
|
---|
158 | NdisSetEvent(&pNetFlt->u.s.WinIf.OpenCloseEvent);
|
---|
159 | LogFlow(("<=="__FUNCTION__": pNetFlt (0x%p), Status (0x%x), OpenErrorStatus(0x%x)\n", pNetFlt, Status, OpenErrorStatus));
|
---|
160 | }
|
---|
161 |
|
---|
162 | static void vboxNetFltWinPtRequestsWaitComplete(PVBOXNETFLTINS pNetFlt)
|
---|
163 | {
|
---|
164 | RTSPINLOCKTMP Tmp = RTSPINLOCKTMP_INITIALIZER;
|
---|
165 |
|
---|
166 | /* wait for request to complete */
|
---|
167 | while (vboxNetFltWinAtomicUoReadWinState(pNetFlt->u.s.WinIf.StateFlags).fRequestInfo == VBOXNDISREQUEST_INPROGRESS)
|
---|
168 | {
|
---|
169 | vboxNetFltWinSleep(2);
|
---|
170 | }
|
---|
171 |
|
---|
172 | /*
|
---|
173 | * If the below miniport is going to low power state, complete the queued request
|
---|
174 | */
|
---|
175 | RTSpinlockAcquireNoInts(pNetFlt->hSpinlock, &Tmp);
|
---|
176 | if (pNetFlt->u.s.WinIf.StateFlags.fRequestInfo & VBOXNDISREQUEST_QUEUED)
|
---|
177 | {
|
---|
178 | /* mark the request as InProgress before posting it to RequestComplete */
|
---|
179 | pNetFlt->u.s.WinIf.StateFlags.fRequestInfo = VBOXNDISREQUEST_INPROGRESS;
|
---|
180 | RTSpinlockReleaseNoInts(pNetFlt->hSpinlock, &Tmp);
|
---|
181 | vboxNetFltWinPtRequestComplete(pNetFlt, &pNetFlt->u.s.WinIf.PassDownRequest, NDIS_STATUS_FAILURE);
|
---|
182 | }
|
---|
183 | else
|
---|
184 | {
|
---|
185 | RTSpinlockReleaseNoInts(pNetFlt->hSpinlock, &Tmp);
|
---|
186 | }
|
---|
187 | }
|
---|
188 |
|
---|
189 | DECLHIDDEN(NDIS_STATUS) vboxNetFltWinPtDoUnbinding(PVBOXNETFLTINS pNetFlt, bool bOnUnbind)
|
---|
190 | {
|
---|
191 | NDIS_STATUS Status;
|
---|
192 | RTSPINLOCKTMP Tmp = RTSPINLOCKTMP_INITIALIZER;
|
---|
193 | uint64_t NanoTS = RTTimeSystemNanoTS();
|
---|
194 | int cPPUsage;
|
---|
195 |
|
---|
196 | LogFlow(("==>"__FUNCTION__": pNetFlt 0x%p\n", pNetFlt));
|
---|
197 |
|
---|
198 | Assert(KeGetCurrentIrql() == PASSIVE_LEVEL);
|
---|
199 |
|
---|
200 | Assert(vboxNetFltWinGetOpState(&pNetFlt->u.s.WinIf.PtState) == kVBoxNetDevOpState_Initialized);
|
---|
201 |
|
---|
202 | RTSpinlockAcquireNoInts(pNetFlt->hSpinlock, &Tmp);
|
---|
203 |
|
---|
204 | ASMAtomicUoWriteBool(&pNetFlt->fDisconnectedFromHost, true);
|
---|
205 | ASMAtomicUoWriteBool(&pNetFlt->fRediscoveryPending, false);
|
---|
206 | ASMAtomicUoWriteU64(&pNetFlt->NanoTSLastRediscovery, NanoTS);
|
---|
207 |
|
---|
208 | vboxNetFltWinSetOpState(&pNetFlt->u.s.WinIf.PtState, kVBoxNetDevOpState_Deinitializing);
|
---|
209 | if (!bOnUnbind)
|
---|
210 | {
|
---|
211 | vboxNetFltWinSetOpState(&pNetFlt->u.s.WinIf.MpState, kVBoxNetDevOpState_Deinitializing);
|
---|
212 | }
|
---|
213 |
|
---|
214 | RTSpinlockReleaseNoInts(pNetFlt->hSpinlock, &Tmp);
|
---|
215 |
|
---|
216 | vboxNetFltWinPtRequestsWaitComplete(pNetFlt);
|
---|
217 |
|
---|
218 | vboxNetFltWinWaitDereference(&pNetFlt->u.s.WinIf.MpState);
|
---|
219 | vboxNetFltWinWaitDereference(&pNetFlt->u.s.WinIf.PtState);
|
---|
220 |
|
---|
221 | /* check packet pool is empty */
|
---|
222 | cPPUsage = NdisPacketPoolUsage(pNetFlt->u.s.WinIf.hSendPacketPool);
|
---|
223 | Assert(cPPUsage == 0);
|
---|
224 | cPPUsage = NdisPacketPoolUsage(pNetFlt->u.s.WinIf.hRecvPacketPool);
|
---|
225 | Assert(cPPUsage == 0);
|
---|
226 | /* for debugging only, ignore the err in release */
|
---|
227 | NOREF(cPPUsage);
|
---|
228 |
|
---|
229 | if (!bOnUnbind || !vboxNetFltWinMpDeInitializeDeviceInstance(pNetFlt, &Status))
|
---|
230 | {
|
---|
231 | vboxNetFltWinPtCloseInterface(pNetFlt, &Status);
|
---|
232 | vboxNetFltWinSetOpState(&pNetFlt->u.s.WinIf.PtState, kVBoxNetDevOpState_Deinitialized);
|
---|
233 |
|
---|
234 | if (!bOnUnbind)
|
---|
235 | {
|
---|
236 | Assert(vboxNetFltWinGetOpState(&pNetFlt->u.s.WinIf.MpState) == kVBoxNetDevOpState_Deinitializing);
|
---|
237 | vboxNetFltWinSetOpState(&pNetFlt->u.s.WinIf.MpState, kVBoxNetDevOpState_Deinitialized);
|
---|
238 | }
|
---|
239 | else
|
---|
240 | {
|
---|
241 | Assert(vboxNetFltWinGetOpState(&pNetFlt->u.s.WinIf.MpState) == kVBoxNetDevOpState_Deinitialized);
|
---|
242 | }
|
---|
243 | }
|
---|
244 | else
|
---|
245 | {
|
---|
246 | Assert(vboxNetFltWinGetOpState(&pNetFlt->u.s.WinIf.MpState) == kVBoxNetDevOpState_Deinitialized);
|
---|
247 | }
|
---|
248 |
|
---|
249 | LogFlow(("<=="__FUNCTION__": pNetFlt 0x%p\n", pNetFlt));
|
---|
250 |
|
---|
251 | return Status;
|
---|
252 | }
|
---|
253 |
|
---|
254 | static VOID vboxNetFltWinPtUnbindAdapter(OUT PNDIS_STATUS pStatus,
|
---|
255 | IN NDIS_HANDLE hContext,
|
---|
256 | IN NDIS_HANDLE hUnbindContext)
|
---|
257 | {
|
---|
258 | PVBOXNETFLTINS pNetFlt = (PVBOXNETFLTINS)hContext;
|
---|
259 |
|
---|
260 | LogFlow(("==>"__FUNCTION__": pNetFlt (0x%p)\n", pNetFlt));
|
---|
261 |
|
---|
262 | *pStatus = vboxNetFltWinDetachFromInterface(pNetFlt, true);
|
---|
263 | Assert(*pStatus == NDIS_STATUS_SUCCESS);
|
---|
264 |
|
---|
265 | LogFlow(("<=="__FUNCTION__": pNetFlt (0x%p)\n", pNetFlt));
|
---|
266 | }
|
---|
267 |
|
---|
268 | static VOID vboxNetFltWinPtUnloadProtocol()
|
---|
269 | {
|
---|
270 | LogFlow(("==>"__FUNCTION__"\n"));
|
---|
271 | NDIS_STATUS Status = vboxNetFltWinPtDeregister(&g_VBoxNetFltGlobalsWin.Pt);
|
---|
272 | Assert(Status == NDIS_STATUS_SUCCESS);
|
---|
273 | LogFlow(("<=="__FUNCTION__": PtDeregister Status (0x%x)\n", Status));
|
---|
274 | }
|
---|
275 |
|
---|
276 |
|
---|
277 | static VOID vboxNetFltWinPtCloseAdapterComplete(IN NDIS_HANDLE ProtocolBindingContext, IN NDIS_STATUS Status)
|
---|
278 | {
|
---|
279 | PVBOXNETFLTINS pNetFlt = (PVBOXNETFLTINS)ProtocolBindingContext;
|
---|
280 |
|
---|
281 | LogFlow(("==>"__FUNCTION__" : pNetFlt (0x%p), Status (0x%x)\n", pNetFlt, Status));
|
---|
282 | Assert(pNetFlt->u.s.WinIf.OpenCloseStatus == NDIS_STATUS_SUCCESS);
|
---|
283 | Assert(Status == NDIS_STATUS_SUCCESS);
|
---|
284 | Assert(pNetFlt->u.s.WinIf.OpenCloseStatus == NDIS_STATUS_SUCCESS);
|
---|
285 | if (pNetFlt->u.s.WinIf.OpenCloseStatus == NDIS_STATUS_SUCCESS)
|
---|
286 | {
|
---|
287 | pNetFlt->u.s.WinIf.OpenCloseStatus = Status;
|
---|
288 | }
|
---|
289 | NdisSetEvent(&pNetFlt->u.s.WinIf.OpenCloseEvent);
|
---|
290 | LogFlow(("<=="__FUNCTION__" : pNetFlt (0x%p), Status (0x%x)\n", pNetFlt, Status));
|
---|
291 | }
|
---|
292 |
|
---|
293 | static VOID vboxNetFltWinPtResetComplete(IN NDIS_HANDLE hProtocolBindingContext, IN NDIS_STATUS Status)
|
---|
294 | {
|
---|
295 | LogFlow(("==>"__FUNCTION__" : pNetFlt 0x%p, Status 0x%x\n", hProtocolBindingContext, Status));
|
---|
296 | /*
|
---|
297 | * should never be here
|
---|
298 | */
|
---|
299 | Assert(0);
|
---|
300 | LogFlow(("<=="__FUNCTION__" : pNetFlt 0x%p, Status 0x%x\n", hProtocolBindingContext, Status));
|
---|
301 | }
|
---|
302 |
|
---|
303 | static NDIS_STATUS vboxNetFltWinPtHandleQueryInfoComplete(PVBOXNETFLTINS pNetFlt, NDIS_STATUS Status)
|
---|
304 | {
|
---|
305 | PNDIS_REQUEST pRequest = &pNetFlt->u.s.WinIf.PassDownRequest;
|
---|
306 |
|
---|
307 | switch (pRequest->DATA.QUERY_INFORMATION.Oid)
|
---|
308 | {
|
---|
309 | case OID_PNP_CAPABILITIES:
|
---|
310 | {
|
---|
311 | if (Status == NDIS_STATUS_SUCCESS)
|
---|
312 | {
|
---|
313 | if (pRequest->DATA.QUERY_INFORMATION.InformationBufferLength >= sizeof (NDIS_PNP_CAPABILITIES))
|
---|
314 | {
|
---|
315 | PNDIS_PNP_CAPABILITIES pPnPCaps = (PNDIS_PNP_CAPABILITIES)(pRequest->DATA.QUERY_INFORMATION.InformationBuffer);
|
---|
316 | PNDIS_PM_WAKE_UP_CAPABILITIES pPmWuCaps = &pPnPCaps->WakeUpCapabilities;
|
---|
317 | pPmWuCaps->MinMagicPacketWakeUp = NdisDeviceStateUnspecified;
|
---|
318 | pPmWuCaps->MinPatternWakeUp = NdisDeviceStateUnspecified;
|
---|
319 | pPmWuCaps->MinLinkChangeWakeUp = NdisDeviceStateUnspecified;
|
---|
320 | *pNetFlt->u.s.WinIf.pcPDRBytesRW = sizeof (NDIS_PNP_CAPABILITIES);
|
---|
321 | *pNetFlt->u.s.WinIf.pcPDRBytesNeeded = 0;
|
---|
322 | Status = NDIS_STATUS_SUCCESS;
|
---|
323 | }
|
---|
324 | else
|
---|
325 | {
|
---|
326 | Assert(0);
|
---|
327 | *pNetFlt->u.s.WinIf.pcPDRBytesNeeded = sizeof(NDIS_PNP_CAPABILITIES);
|
---|
328 | Status = NDIS_STATUS_RESOURCES;
|
---|
329 | }
|
---|
330 | }
|
---|
331 | break;
|
---|
332 | }
|
---|
333 |
|
---|
334 | case OID_GEN_MAC_OPTIONS:
|
---|
335 | {
|
---|
336 | if (Status == NDIS_STATUS_SUCCESS)
|
---|
337 | {
|
---|
338 | if (pRequest->DATA.QUERY_INFORMATION.InformationBufferLength >= sizeof (ULONG))
|
---|
339 | {
|
---|
340 | pNetFlt->u.s.WinIf.fMacOptions = *(PULONG)pRequest->DATA.QUERY_INFORMATION.InformationBuffer;
|
---|
341 | #ifndef VBOX_LOOPBACK_USEFLAGS
|
---|
342 | /* clearing this flag tells ndis we'll handle loopback ourselves
|
---|
343 | * the ndis layer or nic driver below us would loopback packets as necessary */
|
---|
344 | *(PULONG)pRequest->DATA.QUERY_INFORMATION.InformationBuffer &= ~NDIS_MAC_OPTION_NO_LOOPBACK;
|
---|
345 | #else
|
---|
346 | /* we have to catch loopbacks from the underlying driver, so no duplications will occur,
|
---|
347 | * just indicate NDIS to handle loopbacks for the packets coming from the protocol */
|
---|
348 | *(PULONG)pRequest->DATA.QUERY_INFORMATION.InformationBuffer |= NDIS_MAC_OPTION_NO_LOOPBACK;
|
---|
349 | #endif
|
---|
350 | }
|
---|
351 | else
|
---|
352 | {
|
---|
353 | Assert(0);
|
---|
354 | *pNetFlt->u.s.WinIf.pcPDRBytesNeeded = sizeof (ULONG);
|
---|
355 | Status = NDIS_STATUS_RESOURCES;
|
---|
356 | }
|
---|
357 | }
|
---|
358 | break;
|
---|
359 | }
|
---|
360 |
|
---|
361 | case OID_GEN_CURRENT_PACKET_FILTER:
|
---|
362 | {
|
---|
363 | if (VBOXNETFLT_PROMISCUOUS_SUPPORTED(pNetFlt))
|
---|
364 | {
|
---|
365 | /* we're here _ONLY_ in the passthru mode */
|
---|
366 | Assert(pNetFlt->u.s.WinIf.StateFlags.fProcessingPacketFilter && !pNetFlt->u.s.WinIf.StateFlags.fPPFNetFlt);
|
---|
367 | if (pNetFlt->u.s.WinIf.StateFlags.fProcessingPacketFilter && !pNetFlt->u.s.WinIf.StateFlags.fPPFNetFlt)
|
---|
368 | {
|
---|
369 | Assert(pNetFlt->enmTrunkState != INTNETTRUNKIFSTATE_ACTIVE);
|
---|
370 | vboxNetFltWinDereferenceModePassThru(pNetFlt);
|
---|
371 | vboxNetFltWinDereferenceWinIf(pNetFlt);
|
---|
372 | }
|
---|
373 |
|
---|
374 | if (Status == NDIS_STATUS_SUCCESS)
|
---|
375 | {
|
---|
376 | if (pRequest->DATA.QUERY_INFORMATION.InformationBufferLength >= sizeof (ULONG))
|
---|
377 | {
|
---|
378 | /* the filter request is issued below only in case netflt is not active,
|
---|
379 | * simply update the cache here */
|
---|
380 | /* cache the filter used by upper protocols */
|
---|
381 | pNetFlt->u.s.WinIf.fUpperProtocolSetFilter = *(PULONG)pRequest->DATA.QUERY_INFORMATION.InformationBuffer;
|
---|
382 | pNetFlt->u.s.WinIf.StateFlags.fUpperProtSetFilterInitialized = TRUE;
|
---|
383 | }
|
---|
384 | else
|
---|
385 | {
|
---|
386 | Assert(0);
|
---|
387 | *pNetFlt->u.s.WinIf.pcPDRBytesNeeded = sizeof (ULONG);
|
---|
388 | Status = NDIS_STATUS_RESOURCES;
|
---|
389 | }
|
---|
390 | }
|
---|
391 | }
|
---|
392 | break;
|
---|
393 | }
|
---|
394 |
|
---|
395 | default:
|
---|
396 | Assert(pRequest->DATA.QUERY_INFORMATION.Oid != OID_PNP_QUERY_POWER);
|
---|
397 | break;
|
---|
398 | }
|
---|
399 |
|
---|
400 | *pNetFlt->u.s.WinIf.pcPDRBytesRW = pRequest->DATA.QUERY_INFORMATION.BytesWritten;
|
---|
401 | *pNetFlt->u.s.WinIf.pcPDRBytesNeeded = pRequest->DATA.QUERY_INFORMATION.BytesNeeded;
|
---|
402 |
|
---|
403 | return Status;
|
---|
404 | }
|
---|
405 |
|
---|
406 | static NDIS_STATUS vboxNetFltWinPtHandleSetInfoComplete(PVBOXNETFLTINS pNetFlt, NDIS_STATUS Status)
|
---|
407 | {
|
---|
408 | PNDIS_REQUEST pRequest = &pNetFlt->u.s.WinIf.PassDownRequest;
|
---|
409 |
|
---|
410 | switch (pRequest->DATA.SET_INFORMATION.Oid)
|
---|
411 | {
|
---|
412 | case OID_GEN_CURRENT_PACKET_FILTER:
|
---|
413 | {
|
---|
414 | if (VBOXNETFLT_PROMISCUOUS_SUPPORTED(pNetFlt))
|
---|
415 | {
|
---|
416 | Assert(Status == NDIS_STATUS_SUCCESS);
|
---|
417 | if (pNetFlt->u.s.WinIf.StateFlags.fProcessingPacketFilter)
|
---|
418 | {
|
---|
419 | if (pNetFlt->u.s.WinIf.StateFlags.fPPFNetFlt)
|
---|
420 | {
|
---|
421 | Assert(pNetFlt->enmTrunkState == INTNETTRUNKIFSTATE_ACTIVE);
|
---|
422 | pNetFlt->u.s.WinIf.StateFlags.fPPFNetFlt = 0;
|
---|
423 | if (Status == NDIS_STATUS_SUCCESS)
|
---|
424 | {
|
---|
425 | if (pRequest->DATA.SET_INFORMATION.InformationBufferLength >= sizeof (ULONG))
|
---|
426 | {
|
---|
427 | pNetFlt->u.s.WinIf.fOurSetFilter = *((PULONG)pRequest->DATA.SET_INFORMATION.InformationBuffer);
|
---|
428 | Assert(pNetFlt->u.s.WinIf.fOurSetFilter == NDIS_PACKET_TYPE_PROMISCUOUS);
|
---|
429 | }
|
---|
430 | else
|
---|
431 | {
|
---|
432 | Assert(0);
|
---|
433 | *pNetFlt->u.s.WinIf.pcPDRBytesNeeded = sizeof (ULONG);
|
---|
434 | Status = NDIS_STATUS_RESOURCES;
|
---|
435 | }
|
---|
436 | }
|
---|
437 | vboxNetFltWinDereferenceNetFlt(pNetFlt);
|
---|
438 | }
|
---|
439 | else
|
---|
440 | {
|
---|
441 | Assert(pNetFlt->enmTrunkState != INTNETTRUNKIFSTATE_ACTIVE);
|
---|
442 |
|
---|
443 | if (Status == NDIS_STATUS_SUCCESS)
|
---|
444 | {
|
---|
445 | if (pRequest->DATA.SET_INFORMATION.InformationBufferLength >= sizeof (ULONG))
|
---|
446 | {
|
---|
447 | /* the request was issued when the netflt was not active, simply update the cache here */
|
---|
448 | pNetFlt->u.s.WinIf.fUpperProtocolSetFilter = *((PULONG)pRequest->DATA.SET_INFORMATION.InformationBuffer);
|
---|
449 | pNetFlt->u.s.WinIf.StateFlags.fUpperProtSetFilterInitialized = TRUE;
|
---|
450 | }
|
---|
451 | else
|
---|
452 | {
|
---|
453 | Assert(0);
|
---|
454 | *pNetFlt->u.s.WinIf.pcPDRBytesNeeded = sizeof (ULONG);
|
---|
455 | Status = NDIS_STATUS_RESOURCES;
|
---|
456 | }
|
---|
457 | }
|
---|
458 | vboxNetFltWinDereferenceModePassThru(pNetFlt);
|
---|
459 | }
|
---|
460 |
|
---|
461 | pNetFlt->u.s.WinIf.StateFlags.fProcessingPacketFilter = 0;
|
---|
462 | vboxNetFltWinDereferenceWinIf(pNetFlt);
|
---|
463 | }
|
---|
464 | #ifdef DEBUG_misha
|
---|
465 | else
|
---|
466 | {
|
---|
467 | Assert(0);
|
---|
468 | }
|
---|
469 | #endif
|
---|
470 | }
|
---|
471 | break;
|
---|
472 | }
|
---|
473 |
|
---|
474 | default:
|
---|
475 | Assert(pRequest->DATA.SET_INFORMATION.Oid != OID_PNP_SET_POWER);
|
---|
476 | break;
|
---|
477 | }
|
---|
478 |
|
---|
479 | *pNetFlt->u.s.WinIf.pcPDRBytesRW = pRequest->DATA.SET_INFORMATION.BytesRead;
|
---|
480 | *pNetFlt->u.s.WinIf.pcPDRBytesNeeded = pRequest->DATA.SET_INFORMATION.BytesNeeded;
|
---|
481 |
|
---|
482 | return Status;
|
---|
483 | }
|
---|
484 |
|
---|
485 | DECLHIDDEN(VOID) vboxNetFltWinPtRequestComplete(NDIS_HANDLE hContext, PNDIS_REQUEST pNdisRequest, NDIS_STATUS Status)
|
---|
486 | {
|
---|
487 | PVBOXNETFLTINS pNetFlt = (PVBOXNETFLTINS)hContext;
|
---|
488 | PNDIS_REQUEST pSynchRequest = pNetFlt->u.s.WinIf.pSynchRequest;
|
---|
489 | NDIS_OID Oid = pNetFlt->u.s.WinIf.PassDownRequest.DATA.SET_INFORMATION.Oid;
|
---|
490 |
|
---|
491 | LogFlow(("==>"__FUNCTION__" : pNetFlt (0x%p), pNdisRequest (0x%p), Status (0x%x)\n", pNetFlt, pNdisRequest, Status));
|
---|
492 |
|
---|
493 | if (pSynchRequest == pNdisRequest)
|
---|
494 | {
|
---|
495 | /* asynchronous completion of our sync request */
|
---|
496 | /*1.set the status */
|
---|
497 | pNetFlt->u.s.WinIf.SynchCompletionStatus = Status;
|
---|
498 | /* 2. set event */
|
---|
499 | KeSetEvent(&pNetFlt->u.s.WinIf.hSynchCompletionEvent, 0, FALSE);
|
---|
500 | /* 3. return; */
|
---|
501 |
|
---|
502 | LogFlow(("<=="__FUNCTION__" : pNetFlt (0x%p), pNdisRequest (0x%p), Status (0x%x)\n", pNetFlt, pNdisRequest, Status));
|
---|
503 | return;
|
---|
504 | }
|
---|
505 |
|
---|
506 | Assert(&pNetFlt->u.s.WinIf.PassDownRequest == pNdisRequest);
|
---|
507 | Assert(pNetFlt->u.s.WinIf.StateFlags.fRequestInfo == VBOXNDISREQUEST_INPROGRESS);
|
---|
508 | vboxNetFltWinMpRequestStateComplete(pNetFlt);
|
---|
509 |
|
---|
510 | switch (pNdisRequest->RequestType)
|
---|
511 | {
|
---|
512 | case NdisRequestQueryInformation:
|
---|
513 | Status = vboxNetFltWinPtHandleQueryInfoComplete(pNetFlt, Status);
|
---|
514 | NdisMQueryInformationComplete(pNetFlt->u.s.WinIf.hMiniport, Status);
|
---|
515 | break;
|
---|
516 |
|
---|
517 | case NdisRequestSetInformation:
|
---|
518 | Status = vboxNetFltWinPtHandleSetInfoComplete(pNetFlt, Status);
|
---|
519 | NdisMSetInformationComplete(pNetFlt->u.s.WinIf.hMiniport, Status);
|
---|
520 | break;
|
---|
521 |
|
---|
522 | default:
|
---|
523 | Assert(0);
|
---|
524 | break;
|
---|
525 | }
|
---|
526 |
|
---|
527 | LogFlow(("<=="__FUNCTION__" : pNetFlt (0x%p), pNdisRequest (0x%p), Status (0x%x)\n", pNetFlt, pNdisRequest, Status));
|
---|
528 | }
|
---|
529 |
|
---|
530 | static VOID vboxNetFltWinPtStatus(IN NDIS_HANDLE hProtocolBindingContext, IN NDIS_STATUS GeneralStatus, IN PVOID pvStatusBuffer, IN UINT cbStatusBuffer)
|
---|
531 | {
|
---|
532 | PVBOXNETFLTINS pNetFlt = (PVBOXNETFLTINS)hProtocolBindingContext;
|
---|
533 |
|
---|
534 | LogFlow(("==>"__FUNCTION__" : pNetFlt (0x%p), GeneralStatus (0x%x)\n", pNetFlt, GeneralStatus));
|
---|
535 |
|
---|
536 | if (vboxNetFltWinReferenceWinIf(pNetFlt))
|
---|
537 | {
|
---|
538 | Assert(pNetFlt->u.s.WinIf.hMiniport);
|
---|
539 |
|
---|
540 | if (VBOXNETFLT_PT_STATUS_IS_FILTERED(GeneralStatus))
|
---|
541 | {
|
---|
542 | pNetFlt->u.s.WinIf.MpIndicatedMediaStatus = GeneralStatus;
|
---|
543 | }
|
---|
544 | NdisMIndicateStatus(pNetFlt->u.s.WinIf.hMiniport,
|
---|
545 | GeneralStatus,
|
---|
546 | pvStatusBuffer,
|
---|
547 | cbStatusBuffer);
|
---|
548 |
|
---|
549 | vboxNetFltWinDereferenceWinIf(pNetFlt);
|
---|
550 | }
|
---|
551 | else
|
---|
552 | {
|
---|
553 | if (pNetFlt->u.s.WinIf.hMiniport != NULL
|
---|
554 | && VBOXNETFLT_PT_STATUS_IS_FILTERED(GeneralStatus)
|
---|
555 | )
|
---|
556 | {
|
---|
557 | pNetFlt->u.s.WinIf.MpUnindicatedMediaStatus = GeneralStatus;
|
---|
558 | }
|
---|
559 | }
|
---|
560 |
|
---|
561 | LogFlow(("<=="__FUNCTION__" : pNetFlt (0x%p), GeneralStatus (0x%x)\n", pNetFlt, GeneralStatus));
|
---|
562 | }
|
---|
563 |
|
---|
564 |
|
---|
565 | static VOID vboxNetFltWinPtStatusComplete(IN NDIS_HANDLE hProtocolBindingContext)
|
---|
566 | {
|
---|
567 | PVBOXNETFLTINS pNetFlt = (PVBOXNETFLTINS)hProtocolBindingContext;
|
---|
568 |
|
---|
569 | LogFlow(("==>"__FUNCTION__" : pNetFlt (0x%p)\n", pNetFlt));
|
---|
570 |
|
---|
571 | if (vboxNetFltWinReferenceWinIf(pNetFlt))
|
---|
572 | {
|
---|
573 | NdisMIndicateStatusComplete(pNetFlt->u.s.WinIf.hMiniport);
|
---|
574 |
|
---|
575 | vboxNetFltWinDereferenceWinIf(pNetFlt);
|
---|
576 | }
|
---|
577 |
|
---|
578 | LogFlow(("<=="__FUNCTION__" : pNetFlt (0x%p)\n", pNetFlt));
|
---|
579 | }
|
---|
580 |
|
---|
581 | static VOID vboxNetFltWinPtSendComplete(IN NDIS_HANDLE hProtocolBindingContext, IN PNDIS_PACKET pPacket, IN NDIS_STATUS Status)
|
---|
582 | {
|
---|
583 | PVBOXNETFLTINS pNetFlt = (PVBOXNETFLTINS)hProtocolBindingContext;
|
---|
584 | PVBOXNETFLT_PKTRSVD_PT pSendInfo = (PVBOXNETFLT_PKTRSVD_PT)pPacket->ProtocolReserved;
|
---|
585 | PNDIS_PACKET pOrigPacket = pSendInfo->pOrigPacket;
|
---|
586 | PVOID pBufToFree = pSendInfo->pBufToFree;
|
---|
587 | LogFlow(("==>"__FUNCTION__": pNetFlt (0x%p), pPacket (0x%p), Status (0x%x)\n", pNetFlt, pPacket, Status));
|
---|
588 |
|
---|
589 | #if defined(DEBUG_NETFLT_PACKETS) || !defined(VBOX_LOOPBACK_USEFLAGS)
|
---|
590 | /* @todo: for optimization we could check only for netflt-mode packets
|
---|
591 | * do it for all for now */
|
---|
592 | vboxNetFltWinLbRemoveSendPacket(pNetFlt, pPacket);
|
---|
593 | #endif
|
---|
594 |
|
---|
595 | if (pOrigPacket)
|
---|
596 | {
|
---|
597 | NdisIMCopySendCompletePerPacketInfo(pOrigPacket, pPacket);
|
---|
598 | NdisFreePacket(pPacket);
|
---|
599 | /* the ptk was posted from the upperlying protocol */
|
---|
600 | NdisMSendComplete(pNetFlt->u.s.WinIf.hMiniport, pOrigPacket, Status);
|
---|
601 | }
|
---|
602 | else
|
---|
603 | {
|
---|
604 | /* if the pOrigPacket is zero - the ptk was originated by netFlt send/receive
|
---|
605 | * need to free packet buffers */
|
---|
606 | vboxNetFltWinFreeSGNdisPacket(pPacket, !pBufToFree);
|
---|
607 | }
|
---|
608 |
|
---|
609 | if (pBufToFree)
|
---|
610 | {
|
---|
611 | vboxNetFltWinMemFree(pBufToFree);
|
---|
612 | }
|
---|
613 |
|
---|
614 | vboxNetFltWinDereferenceWinIf(pNetFlt);
|
---|
615 |
|
---|
616 | LogFlow(("<=="__FUNCTION__": pNetFlt (0x%p), pPacket (0x%p), Status (0x%x)\n", pNetFlt, pPacket, Status));
|
---|
617 | }
|
---|
618 |
|
---|
619 | /**
|
---|
620 | * removes searches for the packet in the list and removes it if found
|
---|
621 | * @return true if the packet was found and removed, false - otherwise
|
---|
622 | */
|
---|
623 | static bool vboxNetFltWinRemovePacketFromList(PVBOXNETFLT_INTERLOCKED_SINGLE_LIST pList, PNDIS_PACKET pPacket)
|
---|
624 | {
|
---|
625 | PVBOXNETFLT_PKTRSVD_TRANSFERDATA_PT pTDR = (PVBOXNETFLT_PKTRSVD_TRANSFERDATA_PT)pPacket->ProtocolReserved;
|
---|
626 | return vboxNetFltWinInterlockedSearchListEntry(pList, &pTDR->ListEntry, true /* remove*/);
|
---|
627 | }
|
---|
628 |
|
---|
629 | /**
|
---|
630 | * puts the packet to the tail of the list
|
---|
631 | */
|
---|
632 | static void vboxNetFltWinPutPacketToList(PVBOXNETFLT_INTERLOCKED_SINGLE_LIST pList, PNDIS_PACKET pPacket, PNDIS_BUFFER pOrigBuffer)
|
---|
633 | {
|
---|
634 | PVBOXNETFLT_PKTRSVD_TRANSFERDATA_PT pTDR = (PVBOXNETFLT_PKTRSVD_TRANSFERDATA_PT)pPacket->ProtocolReserved;
|
---|
635 | pTDR->pOrigBuffer = pOrigBuffer;
|
---|
636 | vboxNetFltWinInterlockedPutTail(pList, &pTDR->ListEntry);
|
---|
637 | }
|
---|
638 |
|
---|
639 | static bool vboxNetFltWinPtTransferDataCompleteActive(PVBOXNETFLTINS pNetFltIf, PNDIS_PACKET pPacket, NDIS_STATUS Status)
|
---|
640 | {
|
---|
641 | PNDIS_BUFFER pBuffer;
|
---|
642 | PVBOXNETFLT_PKTRSVD_TRANSFERDATA_PT pTDR;
|
---|
643 |
|
---|
644 | if (!vboxNetFltWinRemovePacketFromList(&pNetFltIf->u.s.WinIf.TransferDataList, pPacket))
|
---|
645 | return false;
|
---|
646 |
|
---|
647 | pTDR = (PVBOXNETFLT_PKTRSVD_TRANSFERDATA_PT)pPacket->ProtocolReserved;
|
---|
648 | Assert(pTDR);
|
---|
649 | Assert(pTDR->pOrigBuffer);
|
---|
650 |
|
---|
651 | do
|
---|
652 | {
|
---|
653 | NdisUnchainBufferAtFront(pPacket, &pBuffer);
|
---|
654 |
|
---|
655 | Assert(pBuffer);
|
---|
656 |
|
---|
657 | NdisFreeBuffer(pBuffer);
|
---|
658 |
|
---|
659 | pBuffer = pTDR->pOrigBuffer;
|
---|
660 |
|
---|
661 | NdisChainBufferAtBack(pPacket, pBuffer);
|
---|
662 |
|
---|
663 | /* data transfer was initiated when the netFlt was active
|
---|
664 | * the netFlt is still retained by us
|
---|
665 | * 1. check if loopback
|
---|
666 | * 2. enqueue packet
|
---|
667 | * 3. release netFlt */
|
---|
668 |
|
---|
669 | if (Status == NDIS_STATUS_SUCCESS)
|
---|
670 | {
|
---|
671 |
|
---|
672 | #ifdef VBOX_LOOPBACK_USEFLAGS
|
---|
673 | if (vboxNetFltWinIsLoopedBackPacket(pPacket))
|
---|
674 | {
|
---|
675 | /* should not be here */
|
---|
676 | Assert(0);
|
---|
677 | }
|
---|
678 | #else
|
---|
679 | PNDIS_PACKET pLb = vboxNetFltWinLbSearchLoopBack(pNetFltIf, pPacket, false);
|
---|
680 | if (pLb)
|
---|
681 | {
|
---|
682 | #ifndef DEBUG_NETFLT_RECV_TRANSFERDATA
|
---|
683 | /* should not be here */
|
---|
684 | Assert(0);
|
---|
685 | #endif
|
---|
686 | if (!vboxNetFltWinLbIsFromIntNet(pLb))
|
---|
687 | {
|
---|
688 | /* the packet is not from int net, need to pass it up to the host */
|
---|
689 | NdisMIndicateReceivePacket(pNetFltIf->u.s.WinIf.hMiniport, &pPacket, 1);
|
---|
690 | /* dereference NetFlt, WinIf will be dereferenced on Packet return */
|
---|
691 | vboxNetFltWinDereferenceNetFlt(pNetFltIf);
|
---|
692 | break;
|
---|
693 | }
|
---|
694 | }
|
---|
695 | #endif
|
---|
696 | else
|
---|
697 | {
|
---|
698 | /* 2. enqueue */
|
---|
699 | /* use the same packet info to put the packet in the processing packet queue */
|
---|
700 | PVBOXNETFLT_PKTRSVD_MP pRecvInfo = (PVBOXNETFLT_PKTRSVD_MP)pPacket->MiniportReserved;
|
---|
701 |
|
---|
702 | VBOXNETFLT_LBVERIFY(pNetFltIf, pPacket);
|
---|
703 |
|
---|
704 | pRecvInfo->pOrigPacket = NULL;
|
---|
705 | pRecvInfo->pBufToFree = NULL;
|
---|
706 |
|
---|
707 | NdisGetPacketFlags(pPacket) = 0;
|
---|
708 | # ifdef VBOXNETFLT_NO_PACKET_QUEUE
|
---|
709 | if (vboxNetFltWinPostIntnet(pNetFltIf, pPacket, 0))
|
---|
710 | {
|
---|
711 | /* drop it */
|
---|
712 | vboxNetFltWinFreeSGNdisPacket(pPacket, true);
|
---|
713 | vboxNetFltWinDereferenceWinIf(pNetFltIf);
|
---|
714 | }
|
---|
715 | else
|
---|
716 | {
|
---|
717 | NdisMIndicateReceivePacket(pNetFltIf->u.s.WinIf.hMiniport, &pPacket, 1);
|
---|
718 | }
|
---|
719 | vboxNetFltWinDereferenceNetFlt(pNetFltIf);
|
---|
720 | break;
|
---|
721 | # else
|
---|
722 | Status = vboxNetFltWinQuEnqueuePacket(pNetFltIf, pPacket, PACKET_MINE);
|
---|
723 | if (Status == NDIS_STATUS_SUCCESS)
|
---|
724 | {
|
---|
725 | break;
|
---|
726 | }
|
---|
727 | Assert(0);
|
---|
728 | # endif
|
---|
729 | }
|
---|
730 | }
|
---|
731 | else
|
---|
732 | {
|
---|
733 | Assert(0);
|
---|
734 | }
|
---|
735 | /* we are here because of error either in data transfer or in enqueueing the packet */
|
---|
736 | vboxNetFltWinFreeSGNdisPacket(pPacket, true);
|
---|
737 | vboxNetFltWinDereferenceNetFlt(pNetFltIf);
|
---|
738 | vboxNetFltWinDereferenceWinIf(pNetFltIf);
|
---|
739 | } while (0);
|
---|
740 |
|
---|
741 | return true;
|
---|
742 | }
|
---|
743 |
|
---|
744 | static VOID vboxNetFltWinPtTransferDataComplete(IN NDIS_HANDLE hProtocolBindingContext,
|
---|
745 | IN PNDIS_PACKET pPacket,
|
---|
746 | IN NDIS_STATUS Status,
|
---|
747 | IN UINT cbTransferred)
|
---|
748 | {
|
---|
749 | PVBOXNETFLTINS pNetFlt = (PVBOXNETFLTINS)hProtocolBindingContext;
|
---|
750 | LogFlow(("==>"__FUNCTION__": pNetFlt (0x%p), pPacket (0x%p), Status (0x%x), cbTransfered (%d)\n", pNetFlt, pPacket, Status, cbTransferred));
|
---|
751 | if (!vboxNetFltWinPtTransferDataCompleteActive(pNetFlt, pPacket, Status))
|
---|
752 | {
|
---|
753 | if (pNetFlt->u.s.WinIf.hMiniport)
|
---|
754 | {
|
---|
755 | NdisMTransferDataComplete(pNetFlt->u.s.WinIf.hMiniport,
|
---|
756 | pPacket,
|
---|
757 | Status,
|
---|
758 | cbTransferred);
|
---|
759 | }
|
---|
760 |
|
---|
761 | vboxNetFltWinDereferenceWinIf(pNetFlt);
|
---|
762 | }
|
---|
763 | /* else - all processing is done with vboxNetFltWinPtTransferDataCompleteActive already */
|
---|
764 |
|
---|
765 | LogFlow(("<=="__FUNCTION__": pNetFlt (0x%p), pPacket (0x%p), Status (0x%x), cbTransfered (%d)\n", pNetFlt, pPacket, Status, cbTransferred));
|
---|
766 | }
|
---|
767 |
|
---|
768 | static INT vboxNetFltWinRecvPacketPassThru(PVBOXNETFLTINS pNetFlt, PNDIS_PACKET pPacket, BOOLEAN bForceIndicate)
|
---|
769 | {
|
---|
770 | Assert(KeGetCurrentIrql() == DISPATCH_LEVEL);
|
---|
771 |
|
---|
772 | PNDIS_PACKET pMyPacket;
|
---|
773 | NDIS_STATUS Status = vboxNetFltWinPrepareRecvPacket(pNetFlt, pPacket, &pMyPacket, true);
|
---|
774 | /* the Status holds the current packet status it will be checked for NDIS_STATUS_RESOURCES later
|
---|
775 | * (see below) */
|
---|
776 | Assert(pMyPacket);
|
---|
777 | if (pMyPacket)
|
---|
778 | {
|
---|
779 | NdisMIndicateReceivePacket(pNetFlt->u.s.WinIf.hMiniport, &pMyPacket, 1);
|
---|
780 | if (Status == NDIS_STATUS_RESOURCES)
|
---|
781 | {
|
---|
782 | NdisDprFreePacket(pMyPacket);
|
---|
783 | return 0;
|
---|
784 | }
|
---|
785 |
|
---|
786 | return 1;
|
---|
787 | }
|
---|
788 |
|
---|
789 | return 0;
|
---|
790 | }
|
---|
791 |
|
---|
792 | /**
|
---|
793 | * process the packet receive in a "passthru" mode
|
---|
794 | */
|
---|
795 | static NDIS_STATUS vboxNetFltWinRecvPassThru(PVBOXNETFLTINS pNetFlt, PNDIS_PACKET pPacket)
|
---|
796 | {
|
---|
797 | Assert(KeGetCurrentIrql() == DISPATCH_LEVEL);
|
---|
798 |
|
---|
799 | NDIS_STATUS Status;
|
---|
800 | PNDIS_PACKET pMyPacket;
|
---|
801 |
|
---|
802 | NdisDprAllocatePacket(&Status, &pMyPacket, pNetFlt->u.s.WinIf.hRecvPacketPool);
|
---|
803 | Assert(Status == NDIS_STATUS_SUCCESS);
|
---|
804 | if (Status == NDIS_STATUS_SUCCESS)
|
---|
805 | {
|
---|
806 | vboxNetFltWinCopyPacketInfoOnRecv(pMyPacket, pPacket, true /* force NDIS_STATUS_RESOURCES */);
|
---|
807 | Assert(NDIS_GET_PACKET_STATUS(pMyPacket) == NDIS_STATUS_RESOURCES);
|
---|
808 |
|
---|
809 | NdisMIndicateReceivePacket(pNetFlt->u.s.WinIf.hMiniport, &pMyPacket, 1);
|
---|
810 |
|
---|
811 | NdisDprFreePacket(pMyPacket);
|
---|
812 | }
|
---|
813 | return Status;
|
---|
814 | }
|
---|
815 |
|
---|
816 | static VOID vboxNetFltWinRecvIndicatePassThru(PVBOXNETFLTINS pNetFlt, NDIS_HANDLE MacReceiveContext,
|
---|
817 | PVOID pHeaderBuffer, UINT cbHeaderBuffer, PVOID pLookAheadBuffer, UINT cbLookAheadBuffer, UINT cbPacket)
|
---|
818 | {
|
---|
819 | /* Note: we're using KeGetCurrentProcessorNumber, which is not entirely correct in case
|
---|
820 | * we're running on 64bit win7+, which can handle > 64 CPUs, however since KeGetCurrentProcessorNumber
|
---|
821 | * always returns the number < than the number of CPUs in the first group, we're guaranteed to have CPU index < 64
|
---|
822 | * @todo: use KeGetCurrentProcessorNumberEx for Win7+ 64 and dynamically extended array */
|
---|
823 | ULONG Proc = KeGetCurrentProcessorNumber();
|
---|
824 | Assert(Proc < RT_ELEMENTS(pNetFlt->u.s.WinIf.abIndicateRxComplete));
|
---|
825 | pNetFlt->u.s.WinIf.abIndicateRxComplete[Proc] = TRUE;
|
---|
826 | switch (pNetFlt->u.s.WinIf.enmMedium)
|
---|
827 | {
|
---|
828 | case NdisMedium802_3:
|
---|
829 | case NdisMediumWan:
|
---|
830 | NdisMEthIndicateReceive(pNetFlt->u.s.WinIf.hMiniport,
|
---|
831 | MacReceiveContext,
|
---|
832 | (PCHAR)pHeaderBuffer,
|
---|
833 | cbHeaderBuffer,
|
---|
834 | pLookAheadBuffer,
|
---|
835 | cbLookAheadBuffer,
|
---|
836 | cbPacket);
|
---|
837 | break;
|
---|
838 | default:
|
---|
839 | Assert(FALSE);
|
---|
840 | break;
|
---|
841 | }
|
---|
842 | }
|
---|
843 |
|
---|
844 | /**
|
---|
845 | * process the ProtocolReceive in an "active" mode
|
---|
846 | *
|
---|
847 | * @return NDIS_STATUS_SUCCESS - the packet is processed
|
---|
848 | * NDIS_STATUS_PENDING - the packet is being processed, we are waiting for the ProtocolTransferDataComplete to be called
|
---|
849 | * NDIS_STATUS_NOT_ACCEPTED - the packet is not needed - typically this is because this is a loopback packet
|
---|
850 | * NDIS_STATUS_FAILURE - packet processing failed
|
---|
851 | */
|
---|
852 | static NDIS_STATUS vboxNetFltWinPtReceiveActive(PVBOXNETFLTINS pNetFlt, NDIS_HANDLE MacReceiveContext, PVOID pHeaderBuffer, UINT cbHeaderBuffer,
|
---|
853 | PVOID pLookaheadBuffer, UINT cbLookaheadBuffer, UINT cbPacket)
|
---|
854 | {
|
---|
855 | NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
|
---|
856 |
|
---|
857 | do
|
---|
858 | {
|
---|
859 | if (cbHeaderBuffer != VBOXNETFLT_PACKET_ETHEADER_SIZE)
|
---|
860 | {
|
---|
861 | Status = NDIS_STATUS_NOT_ACCEPTED;
|
---|
862 | break;
|
---|
863 | }
|
---|
864 |
|
---|
865 | #ifndef DEBUG_NETFLT_RECV_TRANSFERDATA
|
---|
866 | if (cbPacket == cbLookaheadBuffer)
|
---|
867 | {
|
---|
868 | PINTNETSG pSG;
|
---|
869 | PUCHAR pRcvData;
|
---|
870 | #ifndef VBOX_LOOPBACK_USEFLAGS
|
---|
871 | PNDIS_PACKET pLb;
|
---|
872 | #endif
|
---|
873 |
|
---|
874 | /* allocate SG buffer */
|
---|
875 | Status = vboxNetFltWinAllocSG(cbPacket + cbHeaderBuffer, &pSG);
|
---|
876 | if (Status != NDIS_STATUS_SUCCESS)
|
---|
877 | {
|
---|
878 | Assert(0);
|
---|
879 | break;
|
---|
880 | }
|
---|
881 |
|
---|
882 | pRcvData = (PUCHAR)pSG->aSegs[0].pv;
|
---|
883 |
|
---|
884 | NdisMoveMappedMemory(pRcvData, pHeaderBuffer, cbHeaderBuffer);
|
---|
885 |
|
---|
886 | NdisCopyLookaheadData(pRcvData+cbHeaderBuffer,
|
---|
887 | pLookaheadBuffer,
|
---|
888 | cbLookaheadBuffer,
|
---|
889 | pNetFlt->u.s.WinIf.fMacOptions);
|
---|
890 | #ifndef VBOX_LOOPBACK_USEFLAGS
|
---|
891 | pLb = vboxNetFltWinLbSearchLoopBackBySG(pNetFlt, pSG, false);
|
---|
892 | if (pLb)
|
---|
893 | {
|
---|
894 | #ifndef DEBUG_NETFLT_RECV_NOPACKET
|
---|
895 | /* should not be here */
|
---|
896 | Assert(0);
|
---|
897 | #endif
|
---|
898 | if (!vboxNetFltWinLbIsFromIntNet(pLb))
|
---|
899 | {
|
---|
900 | PNDIS_PACKET pMyPacket;
|
---|
901 | pMyPacket = vboxNetFltWinNdisPacketFromSG(pNetFlt, /* PVBOXNETFLTINS */
|
---|
902 | pSG, /* PINTNETSG */
|
---|
903 | pSG, /* PVOID pBufToFree */
|
---|
904 | false, /* bool bToWire */
|
---|
905 | false); /* bool bCopyMemory */
|
---|
906 | if (pMyPacket)
|
---|
907 | {
|
---|
908 | NdisMIndicateReceivePacket(pNetFlt->u.s.WinIf.hMiniport, &pMyPacket, 1);
|
---|
909 | /* dereference the NetFlt here & indicate SUCCESS, which would mean the caller would not do a dereference
|
---|
910 | * the WinIf dereference will be done on packet return */
|
---|
911 | vboxNetFltWinDereferenceNetFlt(pNetFlt);
|
---|
912 | Status = NDIS_STATUS_SUCCESS;
|
---|
913 | }
|
---|
914 | else
|
---|
915 | {
|
---|
916 | vboxNetFltWinMemFree(pSG);
|
---|
917 | Status = NDIS_STATUS_FAILURE;
|
---|
918 | }
|
---|
919 | }
|
---|
920 | else
|
---|
921 | {
|
---|
922 | vboxNetFltWinMemFree(pSG);
|
---|
923 | Status = NDIS_STATUS_NOT_ACCEPTED;
|
---|
924 | }
|
---|
925 | break;
|
---|
926 | }
|
---|
927 | #endif
|
---|
928 | VBOXNETFLT_LBVERIFYSG(pNetFlt, pSG);
|
---|
929 |
|
---|
930 | /* enqueue SG */
|
---|
931 | # ifdef VBOXNETFLT_NO_PACKET_QUEUE
|
---|
932 | if (vboxNetFltWinPostIntnet(pNetFlt, pSG, VBOXNETFLT_PACKET_SG))
|
---|
933 | {
|
---|
934 | /* drop it */
|
---|
935 | vboxNetFltWinMemFree(pSG);
|
---|
936 | vboxNetFltWinDereferenceWinIf(pNetFlt);
|
---|
937 | }
|
---|
938 | else
|
---|
939 | {
|
---|
940 | PNDIS_PACKET pMyPacket = vboxNetFltWinNdisPacketFromSG(pNetFlt, /* PVBOXNETFLTINS */
|
---|
941 | pSG, /* PINTNETSG */
|
---|
942 | pSG, /* PVOID pBufToFree */
|
---|
943 | false, /* bool bToWire */
|
---|
944 | false); /* bool bCopyMemory */
|
---|
945 | Assert(pMyPacket);
|
---|
946 | if (pMyPacket)
|
---|
947 | {
|
---|
948 | NDIS_SET_PACKET_STATUS(pMyPacket, NDIS_STATUS_SUCCESS);
|
---|
949 |
|
---|
950 | DBG_CHECK_PACKET_AND_SG(pMyPacket, pSG);
|
---|
951 |
|
---|
952 | LogFlow(("non-ndis packet info, packet created (%p)\n", pMyPacket));
|
---|
953 | NdisMIndicateReceivePacket(pNetFlt->u.s.WinIf.hMiniport, &pMyPacket, 1);
|
---|
954 | }
|
---|
955 | else
|
---|
956 | {
|
---|
957 | vboxNetFltWinDereferenceWinIf(pNetFlt);
|
---|
958 | Status = NDIS_STATUS_RESOURCES;
|
---|
959 | }
|
---|
960 | }
|
---|
961 | vboxNetFltWinDereferenceNetFlt(pNetFlt);
|
---|
962 | # else
|
---|
963 | Status = vboxNetFltWinQuEnqueuePacket(pNetFlt, pSG, PACKET_SG | PACKET_MINE);
|
---|
964 | if (Status != NDIS_STATUS_SUCCESS)
|
---|
965 | {
|
---|
966 | Assert(0);
|
---|
967 | vboxNetFltWinMemFree(pSG);
|
---|
968 | break;
|
---|
969 | }
|
---|
970 | # endif
|
---|
971 | #endif
|
---|
972 | }
|
---|
973 | else
|
---|
974 | {
|
---|
975 | PNDIS_PACKET pPacket;
|
---|
976 | PNDIS_BUFFER pTransferBuffer;
|
---|
977 | PNDIS_BUFFER pOrigBuffer;
|
---|
978 | PUCHAR pMemBuf;
|
---|
979 | UINT cbBuf = cbPacket + cbHeaderBuffer;
|
---|
980 | UINT cbTransferred;
|
---|
981 |
|
---|
982 | /* allocate NDIS Packet buffer */
|
---|
983 | NdisAllocatePacket(&Status, &pPacket, pNetFlt->u.s.WinIf.hRecvPacketPool);
|
---|
984 | if (Status != NDIS_STATUS_SUCCESS)
|
---|
985 | {
|
---|
986 | Assert(0);
|
---|
987 | break;
|
---|
988 | }
|
---|
989 |
|
---|
990 | VBOXNETFLT_OOB_INIT(pPacket);
|
---|
991 |
|
---|
992 | #ifdef VBOX_LOOPBACK_USEFLAGS
|
---|
993 | /* set "don't loopback" flags */
|
---|
994 | NdisGetPacketFlags(pPacket) = g_VBoxNetFltGlobalsWin.fPacketDontLoopBack;
|
---|
995 | #else
|
---|
996 | NdisGetPacketFlags(pPacket) = 0;
|
---|
997 | #endif
|
---|
998 |
|
---|
999 | Status = vboxNetFltWinMemAlloc((PVOID*)(&pMemBuf), cbBuf);
|
---|
1000 | if (Status != NDIS_STATUS_SUCCESS)
|
---|
1001 | {
|
---|
1002 | Assert(0);
|
---|
1003 | NdisFreePacket(pPacket);
|
---|
1004 | break;
|
---|
1005 | }
|
---|
1006 | NdisAllocateBuffer(&Status, &pTransferBuffer, pNetFlt->u.s.WinIf.hRecvBufferPool, pMemBuf + cbHeaderBuffer, cbPacket);
|
---|
1007 | if (Status != NDIS_STATUS_SUCCESS)
|
---|
1008 | {
|
---|
1009 | Assert(0);
|
---|
1010 | Status = NDIS_STATUS_FAILURE;
|
---|
1011 | NdisFreePacket(pPacket);
|
---|
1012 | vboxNetFltWinMemFree(pMemBuf);
|
---|
1013 | break;
|
---|
1014 | }
|
---|
1015 |
|
---|
1016 | NdisAllocateBuffer(&Status, &pOrigBuffer, pNetFlt->u.s.WinIf.hRecvBufferPool, pMemBuf, cbBuf);
|
---|
1017 | if (Status != NDIS_STATUS_SUCCESS)
|
---|
1018 | {
|
---|
1019 | Assert(0);
|
---|
1020 | Status = NDIS_STATUS_FAILURE;
|
---|
1021 | NdisFreeBuffer(pTransferBuffer);
|
---|
1022 | NdisFreePacket(pPacket);
|
---|
1023 | vboxNetFltWinMemFree(pMemBuf);
|
---|
1024 | break;
|
---|
1025 | }
|
---|
1026 |
|
---|
1027 | NdisChainBufferAtBack(pPacket, pTransferBuffer);
|
---|
1028 |
|
---|
1029 | NdisMoveMappedMemory(pMemBuf, pHeaderBuffer, cbHeaderBuffer);
|
---|
1030 |
|
---|
1031 | vboxNetFltWinPutPacketToList(&pNetFlt->u.s.WinIf.TransferDataList, pPacket, pOrigBuffer);
|
---|
1032 |
|
---|
1033 | #ifdef DEBUG_NETFLT_RECV_TRANSFERDATA
|
---|
1034 | if (cbPacket == cbLookaheadBuffer)
|
---|
1035 | {
|
---|
1036 | NdisCopyLookaheadData(pMemBuf+cbHeaderBuffer,
|
---|
1037 | pLookaheadBuffer,
|
---|
1038 | cbLookaheadBuffer,
|
---|
1039 | pNetFlt->u.s.WinIf.fMacOptions);
|
---|
1040 | }
|
---|
1041 | else
|
---|
1042 | #endif
|
---|
1043 | {
|
---|
1044 | Assert(cbPacket > cbLookaheadBuffer);
|
---|
1045 |
|
---|
1046 | NdisTransferData(&Status, pNetFlt->u.s.WinIf.hBinding, MacReceiveContext,
|
---|
1047 | 0, /* ByteOffset */
|
---|
1048 | cbPacket, pPacket, &cbTransferred);
|
---|
1049 | }
|
---|
1050 |
|
---|
1051 | if (Status != NDIS_STATUS_PENDING)
|
---|
1052 | {
|
---|
1053 | vboxNetFltWinPtTransferDataComplete(pNetFlt, pPacket, Status, cbTransferred);
|
---|
1054 | }
|
---|
1055 | }
|
---|
1056 | } while (0);
|
---|
1057 |
|
---|
1058 | return Status;
|
---|
1059 | }
|
---|
1060 |
|
---|
1061 | static NDIS_STATUS vboxNetFltWinPtReceive(IN NDIS_HANDLE hProtocolBindingContext,
|
---|
1062 | IN NDIS_HANDLE MacReceiveContext,
|
---|
1063 | IN PVOID pHeaderBuffer,
|
---|
1064 | IN UINT cbHeaderBuffer,
|
---|
1065 | IN PVOID pLookAheadBuffer,
|
---|
1066 | IN UINT cbLookAheadBuffer,
|
---|
1067 | IN UINT cbPacket)
|
---|
1068 | {
|
---|
1069 | PVBOXNETFLTINS pNetFlt = (PVBOXNETFLTINS)hProtocolBindingContext;
|
---|
1070 | PNDIS_PACKET pPacket = NULL;
|
---|
1071 | NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
|
---|
1072 | bool bNetFltActive;
|
---|
1073 | bool fWinIfActive = vboxNetFltWinReferenceWinIfNetFlt(pNetFlt, &bNetFltActive);
|
---|
1074 | const bool bPassThruActive = !bNetFltActive;
|
---|
1075 |
|
---|
1076 | LogFlow(("==>"__FUNCTION__" : pNetFlt (0x%p)\n", pNetFlt));
|
---|
1077 |
|
---|
1078 | if (fWinIfActive)
|
---|
1079 | {
|
---|
1080 | do
|
---|
1081 | {
|
---|
1082 | #ifndef DEBUG_NETFLT_RECV_NOPACKET
|
---|
1083 | pPacket = NdisGetReceivedPacket(pNetFlt->u.s.WinIf.hBinding, MacReceiveContext);
|
---|
1084 | if (pPacket)
|
---|
1085 | {
|
---|
1086 | # ifndef VBOX_LOOPBACK_USEFLAGS
|
---|
1087 | PNDIS_PACKET pLb = NULL;
|
---|
1088 | # else
|
---|
1089 | if (vboxNetFltWinIsLoopedBackPacket(pPacket))
|
---|
1090 | {
|
---|
1091 | Assert(0);
|
---|
1092 | /* nothing else to do here, just return the packet */
|
---|
1093 | //NdisReturnPackets(&pPacket, 1);
|
---|
1094 | Status = NDIS_STATUS_NOT_ACCEPTED;
|
---|
1095 | break;
|
---|
1096 | }
|
---|
1097 |
|
---|
1098 | VBOXNETFLT_LBVERIFY(pNetFlt, pPacket);
|
---|
1099 | # endif
|
---|
1100 |
|
---|
1101 | if (bNetFltActive)
|
---|
1102 | {
|
---|
1103 | # ifndef VBOX_LOOPBACK_USEFLAGS
|
---|
1104 | pLb = vboxNetFltWinLbSearchLoopBack(pNetFlt, pPacket, false);
|
---|
1105 | if (!pLb)
|
---|
1106 | # endif
|
---|
1107 | {
|
---|
1108 | VBOXNETFLT_LBVERIFY(pNetFlt, pPacket);
|
---|
1109 |
|
---|
1110 | # ifdef VBOXNETFLT_NO_PACKET_QUEUE
|
---|
1111 | if (vboxNetFltWinPostIntnet(pNetFlt, pPacket, 0))
|
---|
1112 | {
|
---|
1113 | /* drop it */
|
---|
1114 | break;
|
---|
1115 | }
|
---|
1116 | # else
|
---|
1117 | Status = vboxNetFltWinQuEnqueuePacket(pNetFlt, pPacket, PACKET_COPY);
|
---|
1118 | Assert(Status == NDIS_STATUS_SUCCESS);
|
---|
1119 | if (Status == NDIS_STATUS_SUCCESS)
|
---|
1120 | {
|
---|
1121 | //NdisReturnPackets(&pPacket, 1);
|
---|
1122 | fWinIfActive = false;
|
---|
1123 | bNetFltActive = false;
|
---|
1124 | break;
|
---|
1125 | }
|
---|
1126 | # endif
|
---|
1127 | }
|
---|
1128 | # ifndef VBOX_LOOPBACK_USEFLAGS
|
---|
1129 | else if (vboxNetFltWinLbIsFromIntNet(pLb))
|
---|
1130 | {
|
---|
1131 | /* nothing else to do here, just return the packet */
|
---|
1132 | //NdisReturnPackets(&pPacket, 1);
|
---|
1133 | Status = NDIS_STATUS_NOT_ACCEPTED;
|
---|
1134 | break;
|
---|
1135 | }
|
---|
1136 | /* we are here because this is a looped back packet set not from intnet
|
---|
1137 | * we will post it to the upper protocol */
|
---|
1138 | # endif
|
---|
1139 | }
|
---|
1140 |
|
---|
1141 | Assert(Status == STATUS_SUCCESS);
|
---|
1142 | if (Status == STATUS_SUCCESS)
|
---|
1143 | {
|
---|
1144 | # ifndef VBOX_LOOPBACK_USEFLAGS
|
---|
1145 | Assert(!pLb || !vboxNetFltWinLbIsFromIntNet(pLb));
|
---|
1146 | # endif
|
---|
1147 | Status = vboxNetFltWinRecvPassThru(pNetFlt, pPacket);
|
---|
1148 | Assert(Status == STATUS_SUCCESS);
|
---|
1149 | /* we are done with packet processing, and we will
|
---|
1150 | * not receive packet return event for this packet,
|
---|
1151 | * fWinIfActive should be true to ensure we release WinIf*/
|
---|
1152 | Assert(fWinIfActive);
|
---|
1153 | if (Status == STATUS_SUCCESS)
|
---|
1154 | break;
|
---|
1155 | }
|
---|
1156 | else
|
---|
1157 | {
|
---|
1158 | /* intnet processing failed - fall back to no-packet mode */
|
---|
1159 | Assert(bNetFltActive);
|
---|
1160 | Assert(fWinIfActive);
|
---|
1161 | }
|
---|
1162 |
|
---|
1163 | }
|
---|
1164 | #endif /* #ifndef DEBUG_NETFLT_RECV_NOPACKET */
|
---|
1165 |
|
---|
1166 | if (bNetFltActive)
|
---|
1167 | {
|
---|
1168 | Status = vboxNetFltWinPtReceiveActive(pNetFlt, MacReceiveContext, pHeaderBuffer, cbHeaderBuffer,
|
---|
1169 | pLookAheadBuffer, cbLookAheadBuffer, cbPacket);
|
---|
1170 | if (NT_SUCCESS(Status))
|
---|
1171 | {
|
---|
1172 | if (Status != NDIS_STATUS_NOT_ACCEPTED)
|
---|
1173 | {
|
---|
1174 | fWinIfActive = false;
|
---|
1175 | bNetFltActive = false;
|
---|
1176 | }
|
---|
1177 | else
|
---|
1178 | {
|
---|
1179 | #ifndef VBOX_LOOPBACK_USEFLAGS
|
---|
1180 | /* this is a loopback packet, nothing to do here */
|
---|
1181 | #else
|
---|
1182 | Assert(0);
|
---|
1183 | /* should not be here */
|
---|
1184 | #endif
|
---|
1185 | }
|
---|
1186 | break;
|
---|
1187 | }
|
---|
1188 | }
|
---|
1189 |
|
---|
1190 | /* we are done with packet processing, and we will
|
---|
1191 | * not receive packet return event for this packet,
|
---|
1192 | * fWinIfActive should be true to ensure we release WinIf*/
|
---|
1193 | Assert(fWinIfActive);
|
---|
1194 |
|
---|
1195 | vboxNetFltWinRecvIndicatePassThru(pNetFlt, MacReceiveContext, pHeaderBuffer, cbHeaderBuffer, pLookAheadBuffer, cbLookAheadBuffer, cbPacket);
|
---|
1196 | /* the status could contain an error value here in case the the IntNet recv failed,
|
---|
1197 | * ensure we return back success status */
|
---|
1198 | Status = NDIS_STATUS_SUCCESS;
|
---|
1199 |
|
---|
1200 | } while (0);
|
---|
1201 |
|
---|
1202 | if (bNetFltActive)
|
---|
1203 | {
|
---|
1204 | vboxNetFltWinDereferenceNetFlt(pNetFlt);
|
---|
1205 | }
|
---|
1206 | else if (bPassThruActive)
|
---|
1207 | {
|
---|
1208 | vboxNetFltWinDereferenceModePassThru(pNetFlt);
|
---|
1209 | }
|
---|
1210 | if (fWinIfActive)
|
---|
1211 | {
|
---|
1212 | vboxNetFltWinDereferenceWinIf(pNetFlt);
|
---|
1213 | }
|
---|
1214 | }
|
---|
1215 | else
|
---|
1216 | {
|
---|
1217 | Status = NDIS_STATUS_FAILURE;
|
---|
1218 | }
|
---|
1219 |
|
---|
1220 | LogFlow(("<=="__FUNCTION__" : pNetFlt (0x%p)\n", pNetFlt));
|
---|
1221 |
|
---|
1222 | return Status;
|
---|
1223 |
|
---|
1224 | }
|
---|
1225 |
|
---|
1226 | static VOID vboxNetFltWinPtReceiveComplete(NDIS_HANDLE hProtocolBindingContext)
|
---|
1227 | {
|
---|
1228 | PVBOXNETFLTINS pNetFlt = (PVBOXNETFLTINS)hProtocolBindingContext;
|
---|
1229 | ULONG cPackets = 0;
|
---|
1230 | bool bNetFltActive;
|
---|
1231 | bool fWinIfActive = vboxNetFltWinReferenceWinIfNetFlt(pNetFlt, &bNetFltActive);
|
---|
1232 | NDIS_HANDLE hMiniport = pNetFlt->u.s.WinIf.hMiniport;
|
---|
1233 | /* Note: we're using KeGetCurrentProcessorNumber, which is not entirely correct in case
|
---|
1234 | * we're running on 64bit win7+, which can handle > 64 CPUs, however since KeGetCurrentProcessorNumber
|
---|
1235 | * always returns the number < than the number of CPUs in the first group, we're guaranteed to have CPU index < 64
|
---|
1236 | * @todo: use KeGetCurrentProcessorNumberEx for Win7+ 64 and dynamically extended array */
|
---|
1237 | ULONG iProc = KeGetCurrentProcessorNumber();
|
---|
1238 | Assert(iProc < RT_ELEMENTS(pNetFlt->u.s.WinIf.abIndicateRxComplete));
|
---|
1239 |
|
---|
1240 | LogFlow(("==>"__FUNCTION__" : pNetFlt (0x%p)\n", pNetFlt));
|
---|
1241 |
|
---|
1242 | if (hMiniport != NULL && pNetFlt->u.s.WinIf.abIndicateRxComplete[iProc])
|
---|
1243 | {
|
---|
1244 | switch (pNetFlt->u.s.WinIf.enmMedium)
|
---|
1245 | {
|
---|
1246 | case NdisMedium802_3:
|
---|
1247 | case NdisMediumWan:
|
---|
1248 | NdisMEthIndicateReceiveComplete(hMiniport);
|
---|
1249 | break;
|
---|
1250 | default:
|
---|
1251 | Assert(0);
|
---|
1252 | break;
|
---|
1253 | }
|
---|
1254 | }
|
---|
1255 |
|
---|
1256 | pNetFlt->u.s.WinIf.abIndicateRxComplete[iProc] = FALSE;
|
---|
1257 |
|
---|
1258 | if (fWinIfActive)
|
---|
1259 | {
|
---|
1260 | if (bNetFltActive)
|
---|
1261 | {
|
---|
1262 | vboxNetFltWinDereferenceNetFlt(pNetFlt);
|
---|
1263 | }
|
---|
1264 | else
|
---|
1265 | {
|
---|
1266 | vboxNetFltWinDereferenceModePassThru(pNetFlt);
|
---|
1267 | }
|
---|
1268 | vboxNetFltWinDereferenceWinIf(pNetFlt);
|
---|
1269 | }
|
---|
1270 |
|
---|
1271 | LogFlow(("<=="__FUNCTION__" : pNetFlt (0x%p)\n", pNetFlt));
|
---|
1272 | }
|
---|
1273 |
|
---|
1274 | static INT vboxNetFltWinPtReceivePacket(NDIS_HANDLE hProtocolBindingContext, PNDIS_PACKET pPacket)
|
---|
1275 | {
|
---|
1276 | PVBOXNETFLTINS pNetFlt = (PVBOXNETFLTINS)hProtocolBindingContext;
|
---|
1277 | INT cRefCount = 0;
|
---|
1278 | bool bNetFltActive;
|
---|
1279 | bool fWinIfActive = vboxNetFltWinReferenceWinIfNetFlt(pNetFlt, &bNetFltActive);
|
---|
1280 | const bool bPassThruActive = !bNetFltActive;
|
---|
1281 |
|
---|
1282 | LogFlow(("==>"__FUNCTION__" : pNetFlt (0x%p)\n", pNetFlt));
|
---|
1283 |
|
---|
1284 | if (fWinIfActive)
|
---|
1285 | {
|
---|
1286 | do
|
---|
1287 | {
|
---|
1288 | #ifdef VBOX_LOOPBACK_USEFLAGS
|
---|
1289 | if (vboxNetFltWinIsLoopedBackPacket(pPacket))
|
---|
1290 | {
|
---|
1291 | Assert(0);
|
---|
1292 | Log(("lb_rp"));
|
---|
1293 |
|
---|
1294 | /* nothing else to do here, just return the packet */
|
---|
1295 | cRefCount = 0;
|
---|
1296 | //NdisReturnPackets(&pPacket, 1);
|
---|
1297 | break;
|
---|
1298 | }
|
---|
1299 |
|
---|
1300 | VBOXNETFLT_LBVERIFY(pNetFlt, pPacket);
|
---|
1301 | #endif
|
---|
1302 |
|
---|
1303 | if (bNetFltActive)
|
---|
1304 | {
|
---|
1305 | #ifndef VBOX_LOOPBACK_USEFLAGS
|
---|
1306 | PNDIS_PACKET pLb = vboxNetFltWinLbSearchLoopBack(pNetFlt, pPacket, false);
|
---|
1307 | if (!pLb)
|
---|
1308 | #endif
|
---|
1309 | {
|
---|
1310 | #ifndef VBOXNETFLT_NO_PACKET_QUEUE
|
---|
1311 | NDIS_STATUS fStatus;
|
---|
1312 | #endif
|
---|
1313 | bool bResources = NDIS_GET_PACKET_STATUS(pPacket) == NDIS_STATUS_RESOURCES;
|
---|
1314 |
|
---|
1315 | VBOXNETFLT_LBVERIFY(pNetFlt, pPacket);
|
---|
1316 | #ifdef DEBUG_misha
|
---|
1317 | /*TODO: remove this assert.
|
---|
1318 | * this is a temporary assert for debugging purposes:
|
---|
1319 | * we're probably doing something wrong with the packets if the miniport reports NDIS_STATUS_RESOURCES */
|
---|
1320 | Assert(!bResources);
|
---|
1321 | #endif
|
---|
1322 |
|
---|
1323 | #ifdef VBOXNETFLT_NO_PACKET_QUEUE
|
---|
1324 | if (vboxNetFltWinPostIntnet(pNetFlt, pPacket, 0))
|
---|
1325 | {
|
---|
1326 | /* drop it */
|
---|
1327 | cRefCount = 0;
|
---|
1328 | break;
|
---|
1329 | }
|
---|
1330 |
|
---|
1331 | #else
|
---|
1332 | fStatus = vboxNetFltWinQuEnqueuePacket(pNetFlt, pPacket, bResources ? PACKET_COPY : 0);
|
---|
1333 | if (fStatus == NDIS_STATUS_SUCCESS)
|
---|
1334 | {
|
---|
1335 | bNetFltActive = false;
|
---|
1336 | fWinIfActive = false;
|
---|
1337 | if (bResources)
|
---|
1338 | {
|
---|
1339 | cRefCount = 0;
|
---|
1340 | //NdisReturnPackets(&pPacket, 1);
|
---|
1341 | }
|
---|
1342 | else
|
---|
1343 | {
|
---|
1344 | cRefCount = 1;
|
---|
1345 | }
|
---|
1346 | break;
|
---|
1347 | }
|
---|
1348 | else
|
---|
1349 | {
|
---|
1350 | Assert(0);
|
---|
1351 | }
|
---|
1352 | #endif
|
---|
1353 | }
|
---|
1354 | #ifndef VBOX_LOOPBACK_USEFLAGS
|
---|
1355 | else if (vboxNetFltWinLbIsFromIntNet(pLb))
|
---|
1356 | {
|
---|
1357 | /* the packet is from intnet, it has already been set to the host,
|
---|
1358 | * no need for loopng it back to the host again */
|
---|
1359 | /* nothing else to do here, just return the packet */
|
---|
1360 | cRefCount = 0;
|
---|
1361 | //NdisReturnPackets(&pPacket, 1);
|
---|
1362 | break;
|
---|
1363 | }
|
---|
1364 | #endif
|
---|
1365 | }
|
---|
1366 |
|
---|
1367 | cRefCount = vboxNetFltWinRecvPacketPassThru(pNetFlt, pPacket, bNetFltActive);
|
---|
1368 | if (cRefCount)
|
---|
1369 | {
|
---|
1370 | Assert(cRefCount == 1);
|
---|
1371 | fWinIfActive = false;
|
---|
1372 | }
|
---|
1373 |
|
---|
1374 | } while (FALSE);
|
---|
1375 |
|
---|
1376 | if (bNetFltActive)
|
---|
1377 | {
|
---|
1378 | vboxNetFltWinDereferenceNetFlt(pNetFlt);
|
---|
1379 | }
|
---|
1380 | else if (bPassThruActive)
|
---|
1381 | {
|
---|
1382 | vboxNetFltWinDereferenceModePassThru(pNetFlt);
|
---|
1383 | }
|
---|
1384 | if (fWinIfActive)
|
---|
1385 | {
|
---|
1386 | vboxNetFltWinDereferenceWinIf(pNetFlt);
|
---|
1387 | }
|
---|
1388 | }
|
---|
1389 | else
|
---|
1390 | {
|
---|
1391 | cRefCount = 0;
|
---|
1392 | //NdisReturnPackets(&pPacket, 1);
|
---|
1393 | }
|
---|
1394 |
|
---|
1395 | LogFlow(("<=="__FUNCTION__" : pNetFlt (0x%p), cRefCount (%d)\n", pNetFlt, cRefCount));
|
---|
1396 |
|
---|
1397 | return cRefCount;
|
---|
1398 | }
|
---|
1399 |
|
---|
1400 | DECLHIDDEN(bool) vboxNetFltWinPtCloseInterface(PVBOXNETFLTINS pNetFlt, PNDIS_STATUS pStatus)
|
---|
1401 | {
|
---|
1402 | RTSPINLOCKTMP Tmp = RTSPINLOCKTMP_INITIALIZER;
|
---|
1403 |
|
---|
1404 | RTSpinlockAcquireNoInts(pNetFlt->hSpinlock, &Tmp);
|
---|
1405 |
|
---|
1406 | if (pNetFlt->u.s.WinIf.StateFlags.fInterfaceClosing)
|
---|
1407 | {
|
---|
1408 | RTSpinlockReleaseNoInts(pNetFlt->hSpinlock, &Tmp);
|
---|
1409 | Assert(0);
|
---|
1410 | return false;
|
---|
1411 | }
|
---|
1412 | if (pNetFlt->u.s.WinIf.hBinding == NULL)
|
---|
1413 | {
|
---|
1414 | RTSpinlockReleaseNoInts(pNetFlt->hSpinlock, &Tmp);
|
---|
1415 | Assert(0);
|
---|
1416 | return false;
|
---|
1417 | }
|
---|
1418 |
|
---|
1419 | pNetFlt->u.s.WinIf.StateFlags.fInterfaceClosing = TRUE;
|
---|
1420 | RTSpinlockReleaseNoInts(pNetFlt->hSpinlock, &Tmp);
|
---|
1421 |
|
---|
1422 | NdisResetEvent(&pNetFlt->u.s.WinIf.OpenCloseEvent);
|
---|
1423 | NdisCloseAdapter(pStatus, pNetFlt->u.s.WinIf.hBinding);
|
---|
1424 | if (*pStatus == NDIS_STATUS_PENDING)
|
---|
1425 | {
|
---|
1426 | NdisWaitEvent(&pNetFlt->u.s.WinIf.OpenCloseEvent, 0);
|
---|
1427 | *pStatus = pNetFlt->u.s.WinIf.OpenCloseStatus;
|
---|
1428 | }
|
---|
1429 |
|
---|
1430 | Assert (*pStatus == NDIS_STATUS_SUCCESS);
|
---|
1431 |
|
---|
1432 | pNetFlt->u.s.WinIf.hBinding = NULL;
|
---|
1433 |
|
---|
1434 | return true;
|
---|
1435 | }
|
---|
1436 |
|
---|
1437 | static NDIS_STATUS vboxNetFltWinPtPnPSetPower(PVBOXNETFLTINS pNetFlt, NDIS_DEVICE_POWER_STATE enmPowerState)
|
---|
1438 | {
|
---|
1439 | NDIS_DEVICE_POWER_STATE enmPrevPowerState = vboxNetFltWinGetPowerState(&pNetFlt->u.s.WinIf.PtState);
|
---|
1440 | RTSPINLOCKTMP Tmp = RTSPINLOCKTMP_INITIALIZER;
|
---|
1441 |
|
---|
1442 | RTSpinlockAcquireNoInts(pNetFlt->hSpinlock, &Tmp);
|
---|
1443 |
|
---|
1444 | vboxNetFltWinSetPowerState(&pNetFlt->u.s.WinIf.PtState, enmPowerState);
|
---|
1445 |
|
---|
1446 | if (vboxNetFltWinGetPowerState(&pNetFlt->u.s.WinIf.PtState) > NdisDeviceStateD0)
|
---|
1447 | {
|
---|
1448 | if (enmPrevPowerState == NdisDeviceStateD0)
|
---|
1449 | {
|
---|
1450 | pNetFlt->u.s.WinIf.StateFlags.fStandBy = TRUE;
|
---|
1451 | }
|
---|
1452 | RTSpinlockReleaseNoInts(pNetFlt->hSpinlock, &Tmp);
|
---|
1453 | vboxNetFltWinPtRequestsWaitComplete(pNetFlt);
|
---|
1454 | vboxNetFltWinWaitDereference(&pNetFlt->u.s.WinIf.MpState);
|
---|
1455 | vboxNetFltWinWaitDereference(&pNetFlt->u.s.WinIf.PtState);
|
---|
1456 |
|
---|
1457 | /* check packet pool is empty */
|
---|
1458 | UINT cPPUsage = NdisPacketPoolUsage(pNetFlt->u.s.WinIf.hSendPacketPool);
|
---|
1459 | Assert(cPPUsage == 0);
|
---|
1460 | cPPUsage = NdisPacketPoolUsage(pNetFlt->u.s.WinIf.hRecvPacketPool);
|
---|
1461 | Assert(cPPUsage == 0);
|
---|
1462 | /* for debugging only, ignore the err in release */
|
---|
1463 | NOREF(cPPUsage);
|
---|
1464 |
|
---|
1465 | Assert(!pNetFlt->u.s.WinIf.StateFlags.fRequestInfo);
|
---|
1466 | }
|
---|
1467 | else
|
---|
1468 | {
|
---|
1469 | if (enmPrevPowerState > NdisDeviceStateD0)
|
---|
1470 | {
|
---|
1471 | pNetFlt->u.s.WinIf.StateFlags.fStandBy = FALSE;
|
---|
1472 | }
|
---|
1473 |
|
---|
1474 | if (pNetFlt->u.s.WinIf.StateFlags.fRequestInfo & VBOXNDISREQUEST_QUEUED)
|
---|
1475 | {
|
---|
1476 | pNetFlt->u.s.WinIf.StateFlags.fRequestInfo = VBOXNDISREQUEST_INPROGRESS;
|
---|
1477 | RTSpinlockReleaseNoInts(pNetFlt->hSpinlock, &Tmp);
|
---|
1478 |
|
---|
1479 | vboxNetFltWinMpRequestPost(pNetFlt);
|
---|
1480 | }
|
---|
1481 | else
|
---|
1482 | {
|
---|
1483 | RTSpinlockReleaseNoInts(pNetFlt->hSpinlock, &Tmp);
|
---|
1484 | }
|
---|
1485 | }
|
---|
1486 |
|
---|
1487 | return NDIS_STATUS_SUCCESS;
|
---|
1488 | }
|
---|
1489 |
|
---|
1490 |
|
---|
1491 | static NDIS_STATUS vboxNetFltWinPtPnPEvent(IN NDIS_HANDLE hProtocolBindingContext, IN PNET_PNP_EVENT pNetPnPEvent)
|
---|
1492 | {
|
---|
1493 | PVBOXNETFLTINS pNetFlt = (PVBOXNETFLTINS)hProtocolBindingContext;
|
---|
1494 |
|
---|
1495 | LogFlow(("==>"__FUNCTION__": pNetFlt (0x%p), NetEvent (%d)\n", pNetFlt, pNetPnPEvent->NetEvent));
|
---|
1496 |
|
---|
1497 | switch (pNetPnPEvent->NetEvent)
|
---|
1498 | {
|
---|
1499 | case NetEventSetPower:
|
---|
1500 | {
|
---|
1501 | NDIS_DEVICE_POWER_STATE enmPowerState = *((PNDIS_DEVICE_POWER_STATE)pNetPnPEvent->Buffer);
|
---|
1502 | return vboxNetFltWinPtPnPSetPower(pNetFlt, enmPowerState);
|
---|
1503 | }
|
---|
1504 | case NetEventReconfigure:
|
---|
1505 | {
|
---|
1506 | if (!pNetFlt)
|
---|
1507 | {
|
---|
1508 | NdisReEnumerateProtocolBindings(g_VBoxNetFltGlobalsWin.Pt.hProtocol);
|
---|
1509 | }
|
---|
1510 | }
|
---|
1511 | default:
|
---|
1512 | return NDIS_STATUS_SUCCESS;
|
---|
1513 | }
|
---|
1514 |
|
---|
1515 | LogFlow(("<=="__FUNCTION__": pNetFlt (0x%p), NetEvent (%d)\n", pNetFlt, pNetPnPEvent->NetEvent));
|
---|
1516 | }
|
---|
1517 |
|
---|
1518 | #ifdef __cplusplus
|
---|
1519 | # define PTCHARS_40(_p) ((_p).Ndis40Chars)
|
---|
1520 | #else
|
---|
1521 | # define PTCHARS_40(_p) (_p)
|
---|
1522 | #endif
|
---|
1523 |
|
---|
1524 | /**
|
---|
1525 | * register the protocol edge
|
---|
1526 | */
|
---|
1527 | DECLHIDDEN(NDIS_STATUS) vboxNetFltWinPtRegister(PVBOXNETFLTGLOBALS_PT pGlobalsPt, PDRIVER_OBJECT pDriverObject, PUNICODE_STRING pRegistryPathStr)
|
---|
1528 | {
|
---|
1529 | NDIS_PROTOCOL_CHARACTERISTICS PtChars;
|
---|
1530 | NDIS_STRING NameStr;
|
---|
1531 |
|
---|
1532 | NdisInitUnicodeString(&NameStr, VBOXNETFLT_NAME_PROTOCOL);
|
---|
1533 |
|
---|
1534 | NdisZeroMemory(&PtChars, sizeof (PtChars));
|
---|
1535 | PTCHARS_40(PtChars).MajorNdisVersion = VBOXNETFLT_VERSION_PT_NDIS_MAJOR;
|
---|
1536 | PTCHARS_40(PtChars).MinorNdisVersion = VBOXNETFLT_VERSION_PT_NDIS_MINOR;
|
---|
1537 |
|
---|
1538 | PTCHARS_40(PtChars).Name = NameStr;
|
---|
1539 | PTCHARS_40(PtChars).OpenAdapterCompleteHandler = vboxNetFltWinPtOpenAdapterComplete;
|
---|
1540 | PTCHARS_40(PtChars).CloseAdapterCompleteHandler = vboxNetFltWinPtCloseAdapterComplete;
|
---|
1541 | PTCHARS_40(PtChars).SendCompleteHandler = vboxNetFltWinPtSendComplete;
|
---|
1542 | PTCHARS_40(PtChars).TransferDataCompleteHandler = vboxNetFltWinPtTransferDataComplete;
|
---|
1543 | PTCHARS_40(PtChars).ResetCompleteHandler = vboxNetFltWinPtResetComplete;
|
---|
1544 | PTCHARS_40(PtChars).RequestCompleteHandler = vboxNetFltWinPtRequestComplete;
|
---|
1545 | PTCHARS_40(PtChars).ReceiveHandler = vboxNetFltWinPtReceive;
|
---|
1546 | PTCHARS_40(PtChars).ReceiveCompleteHandler = vboxNetFltWinPtReceiveComplete;
|
---|
1547 | PTCHARS_40(PtChars).StatusHandler = vboxNetFltWinPtStatus;
|
---|
1548 | PTCHARS_40(PtChars).StatusCompleteHandler = vboxNetFltWinPtStatusComplete;
|
---|
1549 | PTCHARS_40(PtChars).BindAdapterHandler = vboxNetFltWinPtBindAdapter;
|
---|
1550 | PTCHARS_40(PtChars).UnbindAdapterHandler = vboxNetFltWinPtUnbindAdapter;
|
---|
1551 | PTCHARS_40(PtChars).UnloadHandler = vboxNetFltWinPtUnloadProtocol;
|
---|
1552 | #if !defined(DEBUG_NETFLT_RECV)
|
---|
1553 | PTCHARS_40(PtChars).ReceivePacketHandler = vboxNetFltWinPtReceivePacket;
|
---|
1554 | #endif
|
---|
1555 | PTCHARS_40(PtChars).PnPEventHandler = vboxNetFltWinPtPnPEvent;
|
---|
1556 |
|
---|
1557 | NDIS_STATUS Status;
|
---|
1558 | NdisRegisterProtocol(&Status, &pGlobalsPt->hProtocol, &PtChars, sizeof (PtChars));
|
---|
1559 | Assert(Status == STATUS_SUCCESS);
|
---|
1560 | return Status;
|
---|
1561 | }
|
---|
1562 |
|
---|
1563 | /**
|
---|
1564 | * deregister the protocol edge
|
---|
1565 | */
|
---|
1566 | DECLHIDDEN(NDIS_STATUS) vboxNetFltWinPtDeregister(PVBOXNETFLTGLOBALS_PT pGlobalsPt)
|
---|
1567 | {
|
---|
1568 | if (!pGlobalsPt->hProtocol)
|
---|
1569 | return NDIS_STATUS_SUCCESS;
|
---|
1570 |
|
---|
1571 | NDIS_STATUS Status;
|
---|
1572 |
|
---|
1573 | NdisDeregisterProtocol(&Status, pGlobalsPt->hProtocol);
|
---|
1574 | Assert (Status == NDIS_STATUS_SUCCESS);
|
---|
1575 | if (Status == NDIS_STATUS_SUCCESS)
|
---|
1576 | {
|
---|
1577 | NdisZeroMemory(pGlobalsPt, sizeof (*pGlobalsPt));
|
---|
1578 | }
|
---|
1579 | return Status;
|
---|
1580 | }
|
---|