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