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