VBoxNetFltM-win.cpp revision 3331475701a5b12f98b3cfea07d5dca60072530f
/* $Id$ */
/** @file
* VBoxNetFltM-win.cpp - Bridged Networking Driver, Windows Specific Code.
* Miniport edge
*/
/*
* Copyright (C) 2011 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
* General Public License (GPL) as published by the Free Software
* Foundation, in version 2 as it comes in the "COPYING" file of the
* VirtualBox OSE distribution. VirtualBox OSE is distributed in the
* hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
*/
#include "VBoxNetFltCmn-win.h"
#ifndef VBOXNETADP
{
/* the MP state should be already set to kVBoxNetDevOpState_Initializing, just a paranoia
* in case NDIS for some reason calls us in some irregular way */
if (enmMedium == NdisMediumWan)
UINT i = 0;
for (; i < MediumArraySize; i++)
{
if (MediumArray[i] == enmMedium)
{
*SelectedMediumIndex = i;
break;
}
}
do
{
if (i != MediumArraySize)
{
NdisInterfaceInternal /* 0 */);
break;
}
else
{
}
} while (0);
return Status;
}
/**
* process the packet send in a "passthru" mode
*/
#ifdef VBOXNETFLT_NO_PACKET_QUEUE
, bool bNetFltActive
#endif
)
{
if (Status == NDIS_STATUS_SUCCESS)
{
#if !defined(VBOX_LOOPBACK_USEFLAGS) /* || defined(DEBUG_NETFLT_PACKETS) */
# ifdef VBOXNETFLT_NO_PACKET_QUEUE
if (bNetFltActive)
# else
/* no need for the loop enqueue & check in a passthru mode , ndis will do everything for us */
# endif
#endif
if (Status != NDIS_STATUS_PENDING)
{
#if defined(VBOXNETFLT_NO_PACKET_QUEUE) && !defined(VBOX_LOOPBACK_USEFLAGS)
if (bNetFltActive)
#endif
}
}
return Status;
}
#else /* defined VBOXNETADP */
{
/* check packet pool is empty */
/* for debugging only, ignore the err in release */
return NDIS_STATUS_SUCCESS;
}
static NDIS_STATUS vboxNetFltWinMpReadApplyConfig(PVBOXNETFLTINS pThis, NDIS_HANDLE hMiniportAdapter, NDIS_HANDLE hWrapperConfigurationContext)
{
&Status,
if (Status == NDIS_STATUS_SUCCESS)
{
do
{
int rc;
&strMAC,
// Assert(Status == NDIS_STATUS_SUCCESS);
if (Status == NDIS_STATUS_SUCCESS)
{
if (RT_SUCCESS(rc))
{
break;
}
}
if (RT_SUCCESS(rc))
{
&strMAC,
¶m);
if (Status != NDIS_STATUS_SUCCESS)
{
/* ignore the failure */
}
}
} while (0);
}
else
{
}
return NDIS_STATUS_SUCCESS;
}
DECLHIDDEN(NDIS_STATUS) vboxNetFltWinMpDoInitialization(PVBOXNETFLTINS pNetFlt, NDIS_HANDLE hMiniportAdapter, NDIS_HANDLE hWrapperConfigurationContext)
{
0, /* CheckForHangTimeInSeconds */
NdisInterfaceInternal/* 0 */);
return Status;
}
{
UINT i = 0;
for (; i < MediumArraySize; i++)
{
if (MediumArray[i] == NdisMedium802_3)
{
*SelectedMediumIndex = i;
break;
}
}
if (i != MediumArraySize)
{
#define KEY_PREFIX L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Class\\"
&pPdo,
&pFdo,
NULL, //Next Device Object
NULL,
NULL);
&cbBuf);
if (Status == STATUS_SUCCESS)
{
if (Status == STATUS_SUCCESS)
{
// UCHAR valBuf[sizeof(KEY_VALUE_PARTIAL_INFORMATION) + RTUUID_STR_LENGTH*2 + 10];
// ULONG cLength = sizeof(valBuf);
#define NAME_PREFIX L"\\DEVICE\\"
sizeof(Buf),
&cbBuf);
if (Status == STATUS_SUCCESS)
{
{
if (Status == STATUS_SUCCESS)
{
Status = vboxNetFltWinPtInitBind(&pNetFlt, MiniportAdapterHandle, &RtlStr, WrapperConfigurationContext);
if (Status == STATUS_SUCCESS)
{
#if 0
0);
#endif
}
else
{
}
}
}
else
{
}
}
}
}
}
else
{
}
/* TODO: */
return Status;
}
#endif
{
bool bNetFltActive;
{
if (bNetFltActive)
{
cPassThruRefs = 0;
}
else
{
cNetFltRefs = 0;
}
for (UINT i = 0; i < cNumberOfPackets; i++)
{
pPacket = pPacketArray[i];
if (!cNetFltRefs
#ifdef VBOXNETFLT_NO_PACKET_QUEUE
#else
|| (fStatus = vboxNetFltWinQuEnqueuePacket(pNetFlt, pPacket, VBOXNETFLT_PACKET_SRC_HOST)) != NDIS_STATUS_SUCCESS
#endif
)
{
#ifndef VBOXNETADP
#ifdef VBOXNETFLT_NO_PACKET_QUEUE
, !!cNetFltRefs
#endif
);
#else
if (!cNetFltRefs)
{
# ifdef VBOXNETADP_REPORT_DISCONNECTED
# else
# endif
}
#endif
if (Status != NDIS_STATUS_PENDING)
{
}
else
{
cAdaptRefs--;
}
}
else
{
#ifdef VBOXNETFLT_NO_PACKET_QUEUE
#else
cAdaptRefs--;
cNetFltRefs--;
#endif
}
}
if (cNetFltRefs)
{
}
else if (cPassThruRefs)
{
}
if (cAdaptRefs)
{
}
}
else
{
Assert(0);
if (h)
{
for (UINT i = 0; i < cNumberOfPackets; i++)
{
pPacket = pPacketArray[i];
}
}
}
}
#ifndef VBOXNETADP
{
if (vboxNetFltWinGetOpState(&pNetFlt->u.s.WinIf.PtState) > kVBoxNetDevOpState_Initialized /* protocol unbind in progress */
{
return 0;
}
if (vboxNetFltWinGetOpState(&pNetFlt->u.s.WinIf.PtState) > kVBoxNetDevOpState_Initialized /* protocol unbind in progress */
{
return 0;
}
{
}
{
return 0;
}
return VBOXNDISREQUEST_INPROGRESS;
}
{
if (pNetFlt->u.s.WinIf.PassDownRequest.DATA.QUERY_INFORMATION.Oid == OID_GEN_CURRENT_PACKET_FILTER && VBOXNETFLT_PROMISCUOUS_SUPPORTED(pNetFlt))
{
bool fNetFltActive;
if (fNetFltActive)
{
/* netflt is active, simply return the cached value */
*((PULONG)pNetFlt->u.s.WinIf.PassDownRequest.DATA.QUERY_INFORMATION.InformationBuffer) = pNetFlt->u.s.WinIf.fUpperProtocolSetFilter;
/* we've intercepted the query and completed it */
return NDIS_STATUS_SUCCESS;
}
else if (fWinIfActive)
{
/* we're cleaning it in RequestComplete */
}
}
/* issue the request */
if (Status != NDIS_STATUS_PENDING)
{
}
return Status;
}
{
/* fist check if this is the oid we want to pass down */
switch (Oid)
{
case OID_PNP_QUERY_POWER:
break;
case OID_TCP_TASK_OFFLOAD:
case OID_GEN_SUPPORTED_GUIDS:
break;
default:
{
/* the oid is to be passed down,
* check the device state if we can do it
* and update device state accordingly */
if (uOp)
{
/* save the request info */
pNetFlt->u.s.WinIf.PassDownRequest.DATA.QUERY_INFORMATION.InformationBufferLength = InformationBufferLength;
/* the oid can be processed */
if (!(uOp & VBOXNDISREQUEST_QUEUED))
{
}
}
break;
}
}
LogFlow(("<=="__FUNCTION__": pNetFlt (0x%p), Oid (%s), Status (0x%x)\n", pNetFlt, vboxNetFltWinMpDumpOid(Oid), Status));
return Status;
}
#endif /* ifndef VBOXNETADP*/
static NDIS_STATUS vboxNetFltWinMpHandlePowerState(PVBOXNETFLTINS pNetFlt, NDIS_DEVICE_POWER_STATE enmState)
{
&& enmState != NdisDeviceStateD0)
{
/* invalid state transformation */
Assert(0);
return NDIS_STATUS_FAILURE;
}
#ifndef VBOXNETADP
&& enmState > NdisDeviceStateD0)
{
}
&& enmState == NdisDeviceStateD0)
{
}
#endif
#ifndef VBOXNETADP
{
{
NdisMIndicateStatus(pNetFlt->u.s.WinIf.hMiniport, pNetFlt->u.s.WinIf.MpUnindicatedMediaStatus, NULL, 0);
}
}
else
{
}
#endif
return NDIS_STATUS_SUCCESS;
}
#ifndef VBOXNETADP
{
if (pNetFlt->u.s.WinIf.PassDownRequest.DATA.SET_INFORMATION.Oid == OID_GEN_CURRENT_PACKET_FILTER && VBOXNETFLT_PROMISCUOUS_SUPPORTED(pNetFlt))
{
/* need to disable cleaning promiscuous here ?? */
bool fNetFltActive;
if (fNetFltActive)
{
/* netflt is active, update the cached value */
/* TODO: in case we are are not in promiscuous now, we are issuing a request.
* what should we do in case of a failure?
* i.e. should we update the fUpperProtocolSetFilter in completion routine in this case? etc. */
pNetFlt->u.s.WinIf.fUpperProtocolSetFilter = *((PULONG)pNetFlt->u.s.WinIf.PassDownRequest.DATA.SET_INFORMATION.InformationBuffer);
{
pNetFlt->u.s.WinIf.PassDownRequest.DATA.SET_INFORMATION.InformationBuffer = &pNetFlt->u.s.WinIf.fSetFilterBuffer;
pNetFlt->u.s.WinIf.PassDownRequest.DATA.SET_INFORMATION.InformationBufferLength = sizeof (pNetFlt->u.s.WinIf.fSetFilterBuffer);
/* we'll do dereferencing in request complete */
}
else
{
/* we've intercepted the query and completed it */
return NDIS_STATUS_SUCCESS;
}
}
else if (fWinIfActive)
{
/* dereference on completion */
}
}
if (Status != NDIS_STATUS_PENDING)
{
}
return Status;
}
{
{
return vboxNetFltWinMpRequestPostQuery(pNetFlt);
return vboxNetFltWinMpRequestPostSet(pNetFlt);
default:
return NDIS_STATUS_FAILURE;
}
}
{
switch (Oid)
{
case OID_PNP_SET_POWER:
{
if (InformationBufferLength >= sizeof (NDIS_DEVICE_POWER_STATE))
{
}
else
{
}
if (Status == NDIS_STATUS_SUCCESS)
{
*BytesRead = sizeof (NDIS_DEVICE_POWER_STATE);
*BytesNeeded = 0;
}
else
{
*BytesRead = 0;
*BytesNeeded = sizeof (NDIS_DEVICE_POWER_STATE);
}
break;
}
default:
{
/* the oid is to be passed down,
* check the device state if we can do it
* and update device state accordingly */
if (uOp)
{
/* save the request info */
pNetFlt->u.s.WinIf.PassDownRequest.DATA.SET_INFORMATION.InformationBufferLength = InformationBufferLength;
/* the oid can be processed */
if (!(uOp & VBOXNDISREQUEST_QUEUED))
{
}
}
break;
}
}
LogFlow(("<=="__FUNCTION__": pNetFlt (0x%p), Oid (%s), Status (0x%x)\n", pNetFlt, vboxNetFltWinMpDumpOid(Oid), Status));
return Status;
}
#else
static NDIS_OID g_vboxNetFltWinMpSupportedOids[] =
{
};
{
/* static data */
static NDIS_PNP_CAPABILITIES PnPCaps = {0};
/* default is 4bytes */
*BytesWritten = 0;
*BytesNeeded = 0;
switch (Oid)
{
case OID_GEN_SUPPORTED_LIST:
cbInfo = sizeof (g_vboxNetFltWinMpSupportedOids);
break;
case OID_GEN_HARDWARE_STATUS:
pvInfo = &enmHwStatus;
cbInfo = sizeof (NDIS_HARDWARE_STATUS);
break;
case OID_GEN_MEDIA_SUPPORTED:
case OID_GEN_MEDIA_IN_USE:
cbInfo = sizeof (NDIS_MEDIUM);
break;
break;
break;
break;
case OID_GEN_MAC_OPTIONS:
break;
case OID_GEN_LINK_SPEED:
break;
break;
case OID_GEN_VENDOR_ID:
break;
cbInfo = sizeof (VBOXNETADP_VENDOR_DESC);
break;
break;
case OID_GEN_DRIVER_VERSION:
break;
break;
{
bool bNetFltActive;
if (bActive && bNetFltActive)
{
}
else
{
}
if (bActive)
{
}
if (bNetFltActive)
{
}
else
{
}
}
#else
#endif
break;
break;
case OID_PNP_CAPABILITIES:
if (!bPnPCapsInited)
{
}
cbInfo = sizeof (NDIS_PNP_CAPABILITIES);
break;
case OID_PNP_QUERY_POWER:
break;
case OID_GEN_XMIT_OK:
{
}
else
{
}
*BytesNeeded = sizeof (ULONG64);
break;
case OID_GEN_RCV_OK:
{
}
else
{
}
*BytesNeeded = sizeof (ULONG64);
break;
case OID_GEN_XMIT_ERROR:
break;
case OID_GEN_RCV_ERROR:
break;
case OID_GEN_RCV_NO_BUFFER:
case OID_GEN_RCV_CRC_ERROR:
u32Info = 0;
break;
break;
break;
break;
break;
case OID_802_3_MAC_OPTIONS:
case OID_802_3_XMIT_DEFERRED:
case OID_802_3_RCV_OVERRUN:
case OID_802_3_XMIT_UNDERRUN:
u32Info = 0;
break;
default:
break;
}
if (Status == NDIS_STATUS_SUCCESS)
{
if (cbInfo <= InformationBufferLength)
{
*BytesWritten = cbInfo;
if (cbInfo)
}
else
{
*BytesNeeded = cbInfo;
}
}
LogFlow(("<=="__FUNCTION__": pNetFlt (0x%p), Oid (%s), Status (0x%x)\n", pNetFlt, vboxNetFltWinMpDumpOid(Oid), Status));
return Status;
}
{
*BytesRead = 0;
*BytesNeeded = 0;
switch (Oid)
{
case OID_802_3_MULTICAST_LIST:
{
break;
}
{
break;
}
break;
if (InformationBufferLength != sizeof (ULONG))
{
*BytesNeeded = sizeof (ULONG);
break;
}
break;
if (InformationBufferLength != sizeof (ULONG)){
*BytesNeeded = sizeof(ULONG);
break;
}
break;
case OID_PNP_SET_POWER:
if (InformationBufferLength >= sizeof(NDIS_DEVICE_POWER_STATE))
{
}
else
{
}
if (Status == NDIS_STATUS_SUCCESS)
{
*BytesRead = sizeof (NDIS_DEVICE_POWER_STATE);
*BytesNeeded = 0;
}
else
{
*BytesRead = 0;
*BytesNeeded = sizeof (NDIS_DEVICE_POWER_STATE);
}
break;
default:
break;
}
LogFlow(("<=="__FUNCTION__": pNetFlt (0x%p), Oid (%s), Status (0x%x)\n", pNetFlt, vboxNetFltWinMpDumpOid(Oid), Status));
return Status;
}
#endif
#define VBOXNETFLTDUMP_STRCASE(_t) \
#define VBOXNETFLTDUMP_STRCASE_UNKNOWN() \
default: /*Assert(0);*/ return "Unknown";
{
switch (oid)
{
}
}
DECLHIDDEN(VOID) vboxNetFltWinMpReturnPacket(IN NDIS_HANDLE hMiniportAdapterContext, IN PNDIS_PACKET pPacket)
{
if (pOrigPacket)
{
/* the packet was sent from underlying miniport */
}
else
{
/* the packet was sent from IntNet or it is a packet we allocated on PtReceive for TransferData processing */
}
if (pBufToFree)
{
}
}
{
#ifndef VBOXNETADP
{
return NDIS_STATUS_FAILURE;
}
return Status;
#else
/* should never be here */
Assert(0);
return NDIS_STATUS_FAILURE;
#endif
}
{
#ifndef VBOXNETADP
{
}
else
#endif
{
/* we're NOT called from protocolUnbinAdapter, perform a full disconnect */
#ifndef VBOXNETADP
#endif
}
}
/**
* register the miniport edge
*/
DECLHIDDEN(NDIS_STATUS) vboxNetFltWinMpRegister(PVBOXNETFLTGLOBALS_MP pGlobalsMp, PDRIVER_OBJECT pDriverObject, PUNICODE_STRING pRegistryPathStr)
{
#ifndef VBOXNETADP
NDIS_STATUS Status = NdisIMRegisterLayeredMiniport(pGlobalsMp->hNdisWrapper, &MpChars, sizeof (MpChars), &pGlobalsMp->hMiniport);
#else
#endif
if (Status == NDIS_STATUS_SUCCESS)
{
}
return Status;
}
/**
* deregister the miniport edge
*/
{
#ifndef VBOXNETADP
#endif
}
#ifndef VBOXNETADP
{
pThis);
if (Status == NDIS_STATUS_SUCCESS)
{
{
return NDIS_STATUS_SUCCESS;
}
}
return Status;
}
DECLHIDDEN(bool) vboxNetFltWinMpDeInitializeDeviceInstance(PVBOXNETFLTINS pThis, PNDIS_STATUS pStatus)
{
{
Status = NdisIMCancelInitializeDeviceInstance(g_VBoxNetFltGlobalsWin.Mp.hMiniport, &pThis->u.s.WinIf.MpDeviceName);
if (Status == NDIS_STATUS_SUCCESS)
{
/* we've canceled the initialization successfully */
}
else
{
}
}
{
if (Status != NDIS_STATUS_SUCCESS)
{
}
return true;
}
return false;
}
#endif