mirror of
https://github.com/arehnman/yttrium-virtio-gpu.git
synced 2026-10-31 02:05:04 +00:00
SDV is modern mode fails without any information if there are source files with '-' sign in the name. This is preparation change for further work with modern SDV. Signed-off-by: Yuri Benditovich <[email protected]>
817 lines
29 KiB
C++
Executable File
817 lines
29 KiB
C++
Executable File
/*
|
|
* This file contains NDIS OID support procedures, common for NDIS5 and NDIS6
|
|
*
|
|
* Copyright (c) 2008-2017 Red Hat, Inc.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions
|
|
* are met :
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
* documentation and / or other materials provided with the distribution.
|
|
* 3. Neither the names of the copyright holders nor the names of their contributors
|
|
* may be used to endorse or promote products derived from this software
|
|
* without specific prior written permission.
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND
|
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
* ARE DISCLAIMED.IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE
|
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
* SUCH DAMAGE.
|
|
*/
|
|
#include "ParaNdis-Oid.h"
|
|
#include "kdebugprint.h"
|
|
#include "Trace.h"
|
|
#ifdef NETKVM_WPP_ENABLED
|
|
#include "ParaNdis_Oid.tmh"
|
|
#endif
|
|
|
|
static const char VendorName[] = "Red Hat";
|
|
|
|
static UCHAR FORCEINLINE hexdigit(UCHAR nibble)
|
|
{
|
|
UCHAR c = nibble & 0xf;
|
|
c += (c <= 9) ? 0 : 7;
|
|
c += '0';
|
|
return c;
|
|
}
|
|
|
|
/**********************************************************
|
|
Common implementation of copy operation when OID is set
|
|
pOid->Flags (if used) controls when the source data may be truncated or padded on copy
|
|
Parameters:
|
|
tOidDesc *pOid - descriptor of OID
|
|
PVOID pDest - buffer to receive data sent by NDIS
|
|
ULONG ulSize - size of data to copy
|
|
Return value:
|
|
SUCCESS or NDIS error code if target buffer size is wrong
|
|
Rules:
|
|
|
|
PDEST <>OK SIZE PAYLOAD SZ
|
|
NULL any n/a any fail
|
|
BUFF any 0 any success, none copied
|
|
BUFF any SZ ==SZ success, copied SZ
|
|
BUFF !lessok SZ <SZ fail (small), none copied
|
|
BUFF !moreok SZ >SZ fail (overflow), none copied
|
|
BUFF lessok SZ <SZ success, SZ cleared, payload sz copied
|
|
BUFF moreok SZ >SZ success, copied SZ
|
|
***************************************************/
|
|
NDIS_STATUS ParaNdis_OidSetCopy(
|
|
tOidDesc *pOid,
|
|
PVOID pDest,
|
|
ULONG ulSize)
|
|
{
|
|
NDIS_STATUS status = NDIS_STATUS_SUCCESS;
|
|
if (!pDest)
|
|
{
|
|
status = NDIS_STATUS_INVALID_OID;
|
|
*(pOid->pBytesRead) = 0;
|
|
*(pOid->pBytesNeeded) = 0;
|
|
}
|
|
else if (ulSize)
|
|
{
|
|
if (pOid->InformationBufferLength < ulSize)
|
|
{
|
|
if (pOid->ulToDoFlags & ohfSetLessOK)
|
|
{
|
|
*(pOid->pBytesRead) = pOid->InformationBufferLength;
|
|
NdisZeroMemory(pDest, ulSize);
|
|
NdisMoveMemory(pDest, pOid->InformationBuffer, pOid->InformationBufferLength);
|
|
}
|
|
else
|
|
{
|
|
status = NDIS_STATUS_BUFFER_TOO_SHORT;
|
|
*(pOid->pBytesRead) = 0;
|
|
*(pOid->pBytesNeeded) = ulSize;
|
|
}
|
|
}
|
|
else if (pOid->InformationBufferLength == ulSize || (pOid->ulToDoFlags & ohfSetMoreOK))
|
|
{
|
|
*(pOid->pBytesRead) = ulSize;
|
|
NdisMoveMemory(pDest, pOid->InformationBuffer, ulSize);
|
|
}
|
|
else
|
|
{
|
|
status = NDIS_STATUS_BUFFER_OVERFLOW;
|
|
*(pOid->pBytesNeeded) = ulSize;
|
|
*(pOid->pBytesRead) = 0;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
*(pOid->pBytesRead) = pOid->InformationBufferLength;
|
|
}
|
|
return status;
|
|
}
|
|
|
|
|
|
/**********************************************************
|
|
Common handler of setting packet filter
|
|
***********************************************************/
|
|
NDIS_STATUS ParaNdis_OnSetPacketFilter(PARANDIS_ADAPTER *pContext, tOidDesc *pOid)
|
|
{
|
|
ULONG newValue;
|
|
NDIS_STATUS status = ParaNdis_OidSetCopy(
|
|
pOid,
|
|
&newValue,
|
|
sizeof(newValue));
|
|
|
|
if (newValue & ~PARANDIS_PACKET_FILTERS)
|
|
status = NDIS_STATUS_INVALID_DATA;
|
|
|
|
if (status == NDIS_STATUS_SUCCESS)
|
|
{
|
|
pContext->PacketFilter = newValue;
|
|
DPrintf(1, "[%s] PACKET FILTER SET TO %x\n", __FUNCTION__, pContext->PacketFilter);
|
|
ParaNdis_UpdateDeviceFilters(pContext);
|
|
}
|
|
return status;
|
|
}
|
|
|
|
void ParaNdis_FillPowerCapabilities(PNDIS_PNP_CAPABILITIES pCaps)
|
|
{
|
|
NdisZeroMemory(pCaps, sizeof(*pCaps));
|
|
pCaps->WakeUpCapabilities.MinMagicPacketWakeUp = NdisDeviceStateUnspecified;
|
|
pCaps->WakeUpCapabilities.MinPatternWakeUp = NdisDeviceStateUnspecified;
|
|
pCaps->WakeUpCapabilities.MinLinkChangeWakeUp = NdisDeviceStateUnspecified;
|
|
}
|
|
|
|
|
|
/**********************************************************
|
|
Common handler of setting multicast list
|
|
***********************************************************/
|
|
NDIS_STATUS ParaNdis_OnOidSetMulticastList(PARANDIS_ADAPTER *pContext, tOidDesc *pOid)
|
|
{
|
|
NDIS_STATUS status;
|
|
status = ParaNdis_SetMulticastList(
|
|
pContext,
|
|
pOid->InformationBuffer,
|
|
pOid->InformationBufferLength,
|
|
pOid->pBytesRead,
|
|
pOid->pBytesNeeded);
|
|
ParaNdis_UpdateDeviceFilters(pContext);
|
|
return status;
|
|
}
|
|
|
|
/**********************************************************
|
|
Common helper of copy operation on GET OID
|
|
Copies data from specified location to NDIS buffer
|
|
64-bit variable will be casted to 32-bit, if specified on pOid->Flags
|
|
|
|
Parameters:
|
|
tOidDesc *pOid - descriptor of OID
|
|
PVOID pInfo - source to copy from
|
|
ULONG ulSize - source info size
|
|
Return value:
|
|
SUCCESS or kind of failure when the dest buffer size is wrong
|
|
Comments:
|
|
pInfo must be non-NULL, otherwise error returned
|
|
ulSize may be 0, then SUCCESS returned without copy
|
|
***********************************************************/
|
|
NDIS_STATUS ParaNdis_OidQueryCopy(
|
|
tOidDesc *pOid,
|
|
PVOID pInfo,
|
|
ULONG ulSize,
|
|
BOOLEAN bFreeInfo)
|
|
{
|
|
NDIS_STATUS status = NDIS_STATUS_SUCCESS;
|
|
*(pOid->pBytesNeeded) = ulSize;
|
|
if (!pInfo)
|
|
{
|
|
status = NDIS_STATUS_INVALID_OID;
|
|
*(pOid->pBytesWritten) = 0;
|
|
*(pOid->pBytesNeeded) = 0;
|
|
}
|
|
else if (pOid->InformationBufferLength >= ulSize)
|
|
{
|
|
if (ulSize) NdisMoveMemory(pOid->InformationBuffer, pInfo, ulSize);
|
|
*(pOid->pBytesWritten) = ulSize;
|
|
*(pOid->pBytesNeeded) = 0;
|
|
}
|
|
else if ((pOid->ulToDoFlags & ohfQuery3264) && pOid->InformationBufferLength == sizeof(ULONG) && ulSize == sizeof(ULONG64))
|
|
{
|
|
ULONG64 u64 = *(ULONG64 *)pInfo;
|
|
ULONG ul = (ULONG)u64;
|
|
NdisMoveMemory(pOid->InformationBuffer, &ul, sizeof(ul));
|
|
*(pOid->pBytesWritten) = sizeof(ul);
|
|
}
|
|
else
|
|
{
|
|
status = NDIS_STATUS_BUFFER_TOO_SHORT;
|
|
*(pOid->pBytesWritten) = 0;
|
|
}
|
|
if (bFreeInfo && pInfo)
|
|
{
|
|
NdisFreeMemory(pInfo, 0, 0);
|
|
}
|
|
return status;
|
|
}
|
|
|
|
/**********************************************************
|
|
Common handler of Oid queries
|
|
Parameters:
|
|
context
|
|
tOidDesc *pOid - filled descriptor of OID operation
|
|
Return value:
|
|
SUCCESS or kind of failure
|
|
***********************************************************/
|
|
NDIS_STATUS ParaNdis_OidQueryCommon(PARANDIS_ADAPTER *pContext, tOidDesc *pOid)
|
|
{
|
|
NDIS_STATUS status = NDIS_STATUS_SUCCESS;
|
|
PVOID pInfo = NULL;
|
|
ULONG ulSize = 0;
|
|
BOOLEAN bFreeInfo = FALSE;
|
|
union _tagtemp
|
|
{
|
|
NDIS_MEDIUM Medium;
|
|
ULONG64 ul64;
|
|
ULONG ul;
|
|
USHORT us;
|
|
NDIS_PNP_CAPABILITIES PMCaps;
|
|
} u;
|
|
#define SETINFO(field, value) pInfo = &u.##field; ulSize = sizeof(u.##field); u.##field = (value)
|
|
switch (pOid->Oid)
|
|
{
|
|
case OID_GEN_SUPPORTED_LIST:
|
|
ParaNdis_GetSupportedOid(&pInfo, &ulSize);
|
|
break;
|
|
case OID_GEN_HARDWARE_STATUS:
|
|
SETINFO(ul, NdisHardwareStatusReady);
|
|
break;
|
|
case OID_GEN_MEDIA_SUPPORTED:
|
|
__fallthrough;
|
|
case OID_GEN_MEDIA_IN_USE:
|
|
SETINFO(Medium, NdisMedium802_3);
|
|
break;
|
|
case OID_GEN_MAXIMUM_LOOKAHEAD:
|
|
SETINFO(ul, pContext->MaxPacketSize.nMaxFullSizeOsRx);
|
|
break;
|
|
case OID_GEN_CURRENT_LOOKAHEAD:
|
|
if (!pContext->DummyLookAhead) pContext->DummyLookAhead = pContext->MaxPacketSize.nMaxFullSizeOsRx;
|
|
pInfo = &pContext->DummyLookAhead;
|
|
ulSize = sizeof(pContext->DummyLookAhead);
|
|
break;
|
|
case OID_GEN_MAXIMUM_FRAME_SIZE:
|
|
SETINFO(ul, pContext->MaxPacketSize.nMaxDataSize);
|
|
break;
|
|
case OID_GEN_TRANSMIT_BUFFER_SPACE:
|
|
{
|
|
ULONG totalFreeTxDescriptors = 0;
|
|
|
|
for (UINT i = 0; i < pContext->nPathBundles; i++)
|
|
{
|
|
totalFreeTxDescriptors += pContext->pPathBundles[i].txPath.GetFreeTXDescriptors();
|
|
}
|
|
SETINFO(ul, pContext->MaxPacketSize.nMaxFullSizeOS * totalFreeTxDescriptors);
|
|
break;
|
|
}
|
|
case OID_GEN_RECEIVE_BUFFER_SPACE:
|
|
SETINFO(ul, pContext->MaxPacketSize.nMaxFullSizeOsRx * pContext->NetMaxReceiveBuffers);
|
|
break;
|
|
case OID_GEN_RECEIVE_BLOCK_SIZE:
|
|
SETINFO(ul, pContext->MaxPacketSize.nMaxFullSizeOsRx);
|
|
break;
|
|
case OID_GEN_TRANSMIT_BLOCK_SIZE:
|
|
__fallthrough;
|
|
case OID_GEN_MAXIMUM_TOTAL_SIZE:
|
|
SETINFO(ul, pContext->MaxPacketSize.nMaxFullSizeOS);
|
|
break;
|
|
case OID_GEN_TRANSMIT_QUEUE_LENGTH:
|
|
{
|
|
// TODO: this is not completely correct, but only if
|
|
// the TX queue is not full
|
|
ULONG totalFreeTxDescriptors = 0;
|
|
|
|
for (UINT i = 0; i < pContext->nPathBundles; i++)
|
|
{
|
|
totalFreeTxDescriptors += pContext->pPathBundles[i].txPath.GetFreeTXDescriptors();
|
|
}
|
|
SETINFO(ul, (pContext->nPathBundles * pContext->maxFreeTxDescriptors) - totalFreeTxDescriptors);
|
|
break;
|
|
}
|
|
case OID_GEN_VENDOR_ID:
|
|
SETINFO(ul, 0x00ffffff);
|
|
break;
|
|
case OID_GEN_VENDOR_DESCRIPTION:
|
|
pInfo = (PVOID)VendorName;
|
|
ulSize = sizeof(VendorName);
|
|
break;
|
|
|
|
case OID_GEN_VENDOR_DRIVER_VERSION:
|
|
SETINFO(ul, ((ULONG)ParandisVersion.major << 16) | ParandisVersion.minor);
|
|
break;
|
|
case OID_GEN_CURRENT_PACKET_FILTER:
|
|
pInfo = &pContext->PacketFilter;
|
|
ulSize = sizeof(pContext->PacketFilter);
|
|
break;
|
|
case OID_GEN_DRIVER_VERSION:
|
|
SETINFO(us, ((USHORT)ParandisVersion.major << 8) | ParandisVersion.minor);
|
|
break;
|
|
case OID_GEN_MAC_OPTIONS:
|
|
{
|
|
ULONG options = NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA |
|
|
NDIS_MAC_OPTION_TRANSFERS_NOT_PEND |
|
|
NDIS_MAC_OPTION_NO_LOOPBACK;
|
|
if (IsPrioritySupported(pContext))
|
|
options |= NDIS_MAC_OPTION_8021P_PRIORITY;
|
|
if (IsVlanSupported(pContext))
|
|
options |= NDIS_MAC_OPTION_8021Q_VLAN;
|
|
SETINFO(ul, options);
|
|
}
|
|
break;
|
|
case OID_GEN_MAXIMUM_SEND_PACKETS:
|
|
// This OID is obsolete according to the documentation
|
|
// but HCK test suite fails if driver doesn't support it
|
|
// HCK test that fails: 1c_OidsDeviceIoControl
|
|
{
|
|
ULONG totalFreeTxDescriptors = 0;
|
|
|
|
for (UINT i = 0; i < pContext->nPathBundles; i++)
|
|
{
|
|
totalFreeTxDescriptors += pContext->pPathBundles[i].txPath.GetFreeTXDescriptors();
|
|
}
|
|
|
|
SETINFO(ul, totalFreeTxDescriptors);
|
|
break;
|
|
}
|
|
case OID_802_3_PERMANENT_ADDRESS:
|
|
pInfo = pContext->PermanentMacAddress;
|
|
ulSize = sizeof(pContext->PermanentMacAddress);
|
|
break;
|
|
case OID_802_3_CURRENT_ADDRESS:
|
|
pInfo = pContext->CurrentMacAddress;
|
|
ulSize = sizeof(pContext->CurrentMacAddress);
|
|
break;
|
|
case OID_PNP_QUERY_POWER:
|
|
// size if 0, just to indicate success
|
|
pInfo = &status;
|
|
break;
|
|
case OID_GEN_DIRECTED_BYTES_XMIT:
|
|
SETINFO(ul64, pContext->Statistics.ifHCOutUcastOctets);
|
|
break;
|
|
case OID_GEN_DIRECTED_FRAMES_XMIT:
|
|
SETINFO(ul64, pContext->Statistics.ifHCOutUcastPkts);
|
|
break;
|
|
case OID_GEN_MULTICAST_BYTES_XMIT:
|
|
SETINFO(ul64, pContext->Statistics.ifHCOutMulticastOctets);
|
|
break;
|
|
case OID_GEN_MULTICAST_FRAMES_XMIT:
|
|
SETINFO(ul64, pContext->Statistics.ifHCOutMulticastPkts);
|
|
break;
|
|
case OID_GEN_BROADCAST_BYTES_XMIT:
|
|
SETINFO(ul64, pContext->Statistics.ifHCOutBroadcastOctets);
|
|
break;
|
|
case OID_GEN_BROADCAST_FRAMES_XMIT:
|
|
SETINFO(ul64, pContext->Statistics.ifHCOutBroadcastPkts);
|
|
break;
|
|
case OID_GEN_DIRECTED_BYTES_RCV:
|
|
SETINFO(ul64, pContext->Statistics.ifHCInUcastOctets);
|
|
break;
|
|
case OID_GEN_DIRECTED_FRAMES_RCV:
|
|
SETINFO(ul64, pContext->Statistics.ifHCInUcastPkts);
|
|
break;
|
|
case OID_GEN_MULTICAST_BYTES_RCV:
|
|
SETINFO(ul64, pContext->Statistics.ifHCInMulticastOctets);
|
|
break;
|
|
case OID_GEN_MULTICAST_FRAMES_RCV:
|
|
SETINFO(ul64, pContext->Statistics.ifHCInMulticastPkts);
|
|
break;
|
|
case OID_GEN_BROADCAST_BYTES_RCV:
|
|
SETINFO(ul64, pContext->Statistics.ifHCInBroadcastOctets);
|
|
break;
|
|
case OID_GEN_BROADCAST_FRAMES_RCV:
|
|
SETINFO(ul64, pContext->Statistics.ifHCInBroadcastPkts);
|
|
break;
|
|
case OID_GEN_XMIT_OK:
|
|
SETINFO(ul64,
|
|
pContext->Statistics.ifHCOutUcastPkts +
|
|
pContext->Statistics.ifHCOutMulticastPkts +
|
|
pContext->Statistics.ifHCOutBroadcastPkts);
|
|
break;
|
|
case OID_GEN_RCV_OK:
|
|
SETINFO(ul64,
|
|
pContext->Statistics.ifHCInUcastPkts +
|
|
pContext->Statistics.ifHCInMulticastPkts +
|
|
pContext->Statistics.ifHCInBroadcastPkts);
|
|
DPrintf(4, "[%s] Total frames %I64u\n", __FUNCTION__, u.ul64);
|
|
break;
|
|
case OID_GEN_XMIT_ERROR:
|
|
SETINFO(ul64, pContext->Statistics.ifOutErrors );
|
|
break;
|
|
case OID_GEN_RCV_ERROR:
|
|
__fallthrough;
|
|
case OID_GEN_RCV_NO_BUFFER:
|
|
__fallthrough;
|
|
case OID_802_3_RCV_OVERRUN:
|
|
__fallthrough;
|
|
case OID_GEN_RCV_CRC_ERROR:
|
|
__fallthrough;
|
|
case OID_802_3_RCV_ERROR_ALIGNMENT:
|
|
__fallthrough;
|
|
case OID_802_3_XMIT_UNDERRUN:
|
|
__fallthrough;
|
|
case OID_802_3_XMIT_ONE_COLLISION:
|
|
__fallthrough;
|
|
case OID_802_3_XMIT_DEFERRED:
|
|
__fallthrough;
|
|
case OID_802_3_XMIT_MAX_COLLISIONS:
|
|
__fallthrough;
|
|
case OID_802_3_XMIT_MORE_COLLISIONS:
|
|
__fallthrough;
|
|
case OID_802_3_XMIT_HEARTBEAT_FAILURE:
|
|
__fallthrough;
|
|
case OID_802_3_XMIT_TIMES_CRS_LOST:
|
|
__fallthrough;
|
|
case OID_802_3_XMIT_LATE_COLLISIONS:
|
|
SETINFO(ul64, 0);
|
|
break;
|
|
case OID_802_3_MULTICAST_LIST:
|
|
pInfo = pContext->MulticastData.MulticastList;
|
|
ulSize = pContext->MulticastData.nofMulticastEntries * ETH_ALEN;
|
|
break;
|
|
case OID_802_3_MAXIMUM_LIST_SIZE:
|
|
SETINFO(ul, PARANDIS_MULTICAST_LIST_SIZE);
|
|
break;
|
|
case OID_PNP_CAPABILITIES:
|
|
pInfo = &u.PMCaps;
|
|
ulSize = sizeof(u.PMCaps);
|
|
ParaNdis_FillPowerCapabilities(&u.PMCaps);
|
|
break;
|
|
case OID_802_3_MAC_OPTIONS:
|
|
SETINFO(ul, 0);
|
|
break;
|
|
case OID_GEN_VLAN_ID:
|
|
SETINFO(ul, pContext->VlanId);
|
|
if (!IsVlanSupported(pContext))
|
|
status = NDIS_STATUS_NOT_SUPPORTED;
|
|
break;
|
|
case OID_PNP_ENABLE_WAKE_UP:
|
|
SETINFO(ul, pContext->ulEnableWakeup);
|
|
break;
|
|
default:
|
|
status = NDIS_STATUS_NOT_SUPPORTED;
|
|
break;
|
|
}
|
|
|
|
if (status == NDIS_STATUS_SUCCESS)
|
|
{
|
|
status = ParaNdis_OidQueryCopy(pOid, pInfo, ulSize, bFreeInfo);
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
|
|
/**********************************************************
|
|
Just gets OID name
|
|
***********************************************************/
|
|
const char *ParaNdis_OidName(NDIS_OID oid)
|
|
{
|
|
#undef MAKECASE
|
|
#define MAKECASE(id) case id: return #id;
|
|
switch (oid)
|
|
{
|
|
MAKECASE(OID_GEN_SUPPORTED_LIST)
|
|
MAKECASE(OID_GEN_HARDWARE_STATUS)
|
|
MAKECASE(OID_GEN_MEDIA_SUPPORTED)
|
|
MAKECASE(OID_GEN_MEDIA_IN_USE)
|
|
MAKECASE(OID_GEN_MAXIMUM_LOOKAHEAD)
|
|
MAKECASE(OID_GEN_MAXIMUM_FRAME_SIZE)
|
|
MAKECASE(OID_GEN_LINK_SPEED)
|
|
MAKECASE(OID_GEN_TRANSMIT_BUFFER_SPACE)
|
|
MAKECASE(OID_GEN_RECEIVE_BUFFER_SPACE)
|
|
MAKECASE(OID_GEN_TRANSMIT_BLOCK_SIZE)
|
|
MAKECASE(OID_GEN_RECEIVE_BLOCK_SIZE)
|
|
MAKECASE(OID_GEN_VENDOR_ID)
|
|
MAKECASE(OID_GEN_VENDOR_DESCRIPTION)
|
|
MAKECASE(OID_GEN_CURRENT_PACKET_FILTER)
|
|
MAKECASE(OID_GEN_CURRENT_LOOKAHEAD)
|
|
MAKECASE(OID_GEN_DRIVER_VERSION)
|
|
MAKECASE(OID_GEN_MAXIMUM_TOTAL_SIZE)
|
|
MAKECASE(OID_GEN_PROTOCOL_OPTIONS)
|
|
MAKECASE(OID_GEN_MAC_OPTIONS)
|
|
MAKECASE(OID_GEN_MAXIMUM_SEND_PACKETS)
|
|
MAKECASE(OID_GEN_VENDOR_DRIVER_VERSION)
|
|
MAKECASE(OID_GEN_SUPPORTED_GUIDS)
|
|
MAKECASE(OID_GEN_NETWORK_LAYER_ADDRESSES)
|
|
MAKECASE(OID_GEN_TRANSPORT_HEADER_OFFSET)
|
|
MAKECASE(OID_GEN_MEDIA_CAPABILITIES)
|
|
MAKECASE(OID_GEN_PHYSICAL_MEDIUM)
|
|
MAKECASE(OID_GEN_XMIT_OK)
|
|
MAKECASE(OID_GEN_RCV_OK)
|
|
MAKECASE(OID_GEN_XMIT_ERROR)
|
|
MAKECASE(OID_GEN_RCV_ERROR)
|
|
MAKECASE(OID_GEN_RCV_NO_BUFFER)
|
|
MAKECASE(OID_GEN_DIRECTED_BYTES_XMIT)
|
|
MAKECASE(OID_GEN_DIRECTED_FRAMES_XMIT)
|
|
MAKECASE(OID_GEN_MULTICAST_BYTES_XMIT)
|
|
MAKECASE(OID_GEN_MULTICAST_FRAMES_XMIT)
|
|
MAKECASE(OID_GEN_BROADCAST_BYTES_XMIT)
|
|
MAKECASE(OID_GEN_BROADCAST_FRAMES_XMIT)
|
|
MAKECASE(OID_GEN_DIRECTED_BYTES_RCV)
|
|
MAKECASE(OID_GEN_DIRECTED_FRAMES_RCV)
|
|
MAKECASE(OID_GEN_MULTICAST_BYTES_RCV)
|
|
MAKECASE(OID_GEN_MULTICAST_FRAMES_RCV)
|
|
MAKECASE(OID_GEN_BROADCAST_BYTES_RCV)
|
|
MAKECASE(OID_GEN_BROADCAST_FRAMES_RCV)
|
|
MAKECASE(OID_GEN_RCV_CRC_ERROR)
|
|
MAKECASE(OID_GEN_TRANSMIT_QUEUE_LENGTH)
|
|
MAKECASE(OID_GEN_GET_TIME_CAPS)
|
|
MAKECASE(OID_GEN_GET_NETCARD_TIME)
|
|
MAKECASE(OID_GEN_NETCARD_LOAD)
|
|
MAKECASE(OID_GEN_DEVICE_PROFILE)
|
|
MAKECASE(OID_GEN_INIT_TIME_MS)
|
|
MAKECASE(OID_GEN_RESET_COUNTS)
|
|
MAKECASE(OID_GEN_MEDIA_SENSE_COUNTS)
|
|
MAKECASE(OID_GEN_VLAN_ID)
|
|
MAKECASE(OID_PNP_CAPABILITIES)
|
|
MAKECASE(OID_PNP_SET_POWER)
|
|
MAKECASE(OID_PNP_QUERY_POWER)
|
|
MAKECASE(OID_PNP_ADD_WAKE_UP_PATTERN)
|
|
MAKECASE(OID_PNP_REMOVE_WAKE_UP_PATTERN)
|
|
MAKECASE(OID_PNP_ENABLE_WAKE_UP)
|
|
MAKECASE(OID_802_3_PERMANENT_ADDRESS)
|
|
MAKECASE(OID_802_3_CURRENT_ADDRESS)
|
|
MAKECASE(OID_802_3_MULTICAST_LIST)
|
|
MAKECASE(OID_802_3_MAXIMUM_LIST_SIZE)
|
|
MAKECASE(OID_802_3_MAC_OPTIONS)
|
|
MAKECASE(OID_802_3_RCV_ERROR_ALIGNMENT)
|
|
MAKECASE(OID_802_3_XMIT_ONE_COLLISION)
|
|
MAKECASE(OID_802_3_XMIT_MORE_COLLISIONS)
|
|
MAKECASE(OID_802_3_XMIT_DEFERRED)
|
|
MAKECASE(OID_802_3_XMIT_MAX_COLLISIONS)
|
|
MAKECASE(OID_802_3_RCV_OVERRUN)
|
|
MAKECASE(OID_802_3_XMIT_UNDERRUN)
|
|
MAKECASE(OID_802_3_XMIT_HEARTBEAT_FAILURE)
|
|
MAKECASE(OID_802_3_XMIT_TIMES_CRS_LOST)
|
|
MAKECASE(OID_802_3_XMIT_LATE_COLLISIONS)
|
|
MAKECASE(OID_GEN_MACHINE_NAME)
|
|
MAKECASE(OID_TCP_TASK_OFFLOAD)
|
|
MAKECASE(OID_GEN_STATISTICS)
|
|
MAKECASE(OID_GEN_INTERRUPT_MODERATION)
|
|
#if PARANDIS_SUPPORT_RSS
|
|
MAKECASE(OID_GEN_RECEIVE_SCALE_PARAMETERS)
|
|
MAKECASE(OID_GEN_RECEIVE_HASH)
|
|
#endif
|
|
#if PARANDIS_SUPPORT_RSC
|
|
MAKECASE(OID_TCP_RSC_STATISTICS)
|
|
#endif
|
|
MAKECASE(OID_TCP_OFFLOAD_PARAMETERS)
|
|
MAKECASE(OID_OFFLOAD_ENCAPSULATION)
|
|
MAKECASE(OID_IP4_OFFLOAD_STATS)
|
|
MAKECASE(OID_IP6_OFFLOAD_STATS)
|
|
#if NDIS_SUPPORT_NDIS61
|
|
MAKECASE(OID_TCP_TASK_IPSEC_OFFLOAD_V2_ADD_SA)
|
|
MAKECASE(OID_TCP_TASK_IPSEC_OFFLOAD_V2_DELETE_SA)
|
|
MAKECASE(OID_TCP_TASK_IPSEC_OFFLOAD_V2_UPDATE_SA)
|
|
#endif
|
|
#if NDIS_SUPPORT_NDIS620
|
|
MAKECASE(OID_PM_CURRENT_CAPABILITIES)
|
|
MAKECASE(OID_PM_HARDWARE_CAPABILITIES)
|
|
MAKECASE(OID_PM_PARAMETERS)
|
|
MAKECASE(OID_PM_ADD_WOL_PATTERN)
|
|
MAKECASE(OID_PM_REMOVE_WOL_PATTERN)
|
|
MAKECASE(OID_PM_WOL_PATTERN_LIST)
|
|
MAKECASE(OID_PM_ADD_PROTOCOL_OFFLOAD)
|
|
MAKECASE(OID_PM_GET_PROTOCOL_OFFLOAD)
|
|
MAKECASE(OID_PM_REMOVE_PROTOCOL_OFFLOAD)
|
|
MAKECASE(OID_PM_PROTOCOL_OFFLOAD_LIST)
|
|
#endif
|
|
default:
|
|
{
|
|
static UCHAR buffer[9];
|
|
UINT i;
|
|
for (i = 0; i < 8; ++i)
|
|
{
|
|
UCHAR nibble = (UCHAR)((oid >> (28 - i * 4)) & 0xf);
|
|
buffer[i] = hexdigit(nibble);
|
|
}
|
|
return (const char *)buffer;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
/**********************************************************
|
|
Common handler of IP-address assignment (DHCP finish)
|
|
***********************************************************/
|
|
NDIS_STATUS ParaNdis_OnOidSetNetworkAddresses(PARANDIS_ADAPTER *pContext, tOidDesc *pOid)
|
|
{
|
|
UINT i, j, ipV4Count = 0, ipV6Count = 0;
|
|
|
|
NETWORK_ADDRESS_LIST *pnal = (NETWORK_ADDRESS_LIST *)pOid->InformationBuffer;
|
|
if (sizeof(NETWORK_ADDRESS_LIST) < pOid->InformationBufferLength)
|
|
{
|
|
NETWORK_ADDRESS * addr;
|
|
PUCHAR ptr = (PUCHAR)(&pnal->Address[0]);
|
|
|
|
for (i = 0; i < (UINT)pnal->AddressCount; i++)
|
|
{
|
|
addr = (NETWORK_ADDRESS *)ptr;
|
|
if (addr->AddressType == NDIS_PROTOCOL_ID_TCP_IP)
|
|
{
|
|
ipV4Count++;
|
|
} else if (addr->AddressType == NDIS_PROTOCOL_ID_IP6)
|
|
{
|
|
ipV6Count++;
|
|
}
|
|
ptr += RTL_FIELD_SIZE(NETWORK_ADDRESS, AddressLength) + RTL_FIELD_SIZE(NETWORK_ADDRESS, AddressType);
|
|
ptr += addr->AddressLength;
|
|
}
|
|
/*
|
|
* As it was observed on Windows, NETWORK_ADDRESS_LIST contains either V4 or V6 Addresses
|
|
* and thus if we get IPV4 addresses we only change the IPV4 packets, the same applies to IPV6
|
|
*/
|
|
if (ipV4Count)
|
|
{
|
|
pContext->guestAnnouncePackets.DestroyIPV4NBLs();
|
|
}
|
|
if (ipV6Count)
|
|
{
|
|
pContext->guestAnnouncePackets.DestroyIPV6NBLs();
|
|
}
|
|
PUCHAR p = (PUCHAR)(&pnal->Address[0]);
|
|
DPrintf(2, "Received %d addresses, type %d\n", pnal->AddressCount, pnal->AddressType);
|
|
for (i = 0; i < (UINT)pnal->AddressCount; ++i)
|
|
{
|
|
NETWORK_ADDRESS *pna = (NETWORK_ADDRESS *)p;
|
|
ULONG ulBufSize = pna->AddressLength * 2 + 1;
|
|
if (pna->AddressLength == sizeof(NETWORK_ADDRESS_IP)
|
|
&& pnal->AddressType == NDIS_PROTOCOL_ID_TCP_IP)
|
|
{
|
|
PNETWORK_ADDRESS_IP pIP = (PNETWORK_ADDRESS_IP)pna->Address;
|
|
pContext->guestAnnouncePackets.CreateNBL(pIP->in_addr);
|
|
DPrintf(0, "Received IP address %d.%d.%d.%d\n",
|
|
(pIP->in_addr >> 0) & 0xff,
|
|
(pIP->in_addr >> 8) & 0xff,
|
|
(pIP->in_addr >> 16) & 0xff,
|
|
(pIP->in_addr >> 24) & 0xff);
|
|
} else
|
|
{
|
|
if (pna->AddressLength == sizeof(NETWORK_ADDRESS_IP6)
|
|
&& pnal->AddressType == NDIS_PROTOCOL_ID_IP6)
|
|
{
|
|
PNETWORK_ADDRESS_IP6 pIP = (PNETWORK_ADDRESS_IP6)pna->Address;
|
|
pContext->guestAnnouncePackets.CreateNBL(pIP->sin6_addr);
|
|
}
|
|
PUCHAR TempString = (ulBufSize < 100) ? (PUCHAR) ParaNdis_AllocateMemory(pContext, ulBufSize) : NULL;
|
|
if (TempString)
|
|
{
|
|
NdisZeroMemory(TempString, ulBufSize);
|
|
for (j = 0; j < pna->AddressLength; ++j)
|
|
{
|
|
UCHAR digit;
|
|
digit = pna->Address[j] >> 4;
|
|
TempString[j * 2] = hexdigit(digit);
|
|
digit = pna->Address[j] & 0xf;
|
|
TempString[j * 2 + 1] = hexdigit(digit);
|
|
}
|
|
}
|
|
DPrintf(0, "address %d, type %d, len %d (%s)\n",
|
|
i, pna->AddressType, pna->AddressLength, TempString ? (PCHAR) TempString : "do not know");
|
|
if (TempString) NdisFreeMemory(TempString, 0, 0);
|
|
}
|
|
p += RTL_FIELD_SIZE(NETWORK_ADDRESS, AddressLength) + RTL_FIELD_SIZE(NETWORK_ADDRESS, AddressType);
|
|
p += pna->AddressLength;
|
|
}
|
|
}
|
|
*pOid->pBytesRead = pOid->InformationBufferLength;
|
|
return NDIS_STATUS_SUCCESS;
|
|
}
|
|
|
|
/**********************************************************
|
|
Checker of valid size of provided wake-up patter
|
|
Return value: SUCCESS or kind of failure where the buffer is wrong
|
|
***********************************************************/
|
|
static NDIS_STATUS ValidateWakeupPattern(PNDIS_PM_PACKET_PATTERN p, PULONG pValidSize)
|
|
{
|
|
NDIS_STATUS status = NDIS_STATUS_BUFFER_TOO_SHORT;
|
|
|
|
if (*pValidSize < sizeof(*p))
|
|
{
|
|
*pValidSize = sizeof(*p);
|
|
}
|
|
else
|
|
{
|
|
ULONG ul = p->PatternOffset + p->PatternSize;
|
|
if (*pValidSize >= ul) status = NDIS_STATUS_SUCCESS;
|
|
*pValidSize = ul;
|
|
DPrintf(2, "[%s] pattern of %d at %d, mask %d (%s)\n",
|
|
__FUNCTION__, p->PatternSize, p->PatternOffset, p->MaskSize,
|
|
status == NDIS_STATUS_SUCCESS ? "OK" : "Fail");
|
|
}
|
|
return status;
|
|
}
|
|
|
|
|
|
/**********************************************************
|
|
Common handler of wake-up pattern addition
|
|
***********************************************************/
|
|
NDIS_STATUS ParaNdis_OnAddWakeupPattern(PARANDIS_ADAPTER *pContext, tOidDesc *pOid)
|
|
{
|
|
NDIS_STATUS status;
|
|
PNDIS_PM_PACKET_PATTERN pPmPattern = (PNDIS_PM_PACKET_PATTERN) pOid->InformationBuffer;
|
|
ULONG ulValidSize = pOid->InformationBufferLength;
|
|
|
|
UNREFERENCED_PARAMETER(pContext);
|
|
|
|
status = ValidateWakeupPattern(pPmPattern, &ulValidSize);
|
|
if (status == NDIS_STATUS_SUCCESS)
|
|
{
|
|
*pOid->pBytesRead = ulValidSize;
|
|
}
|
|
else
|
|
{
|
|
*pOid->pBytesRead = 0;
|
|
*pOid->pBytesNeeded = ulValidSize;
|
|
}
|
|
// TODO: Apply
|
|
return status;
|
|
}
|
|
|
|
/**********************************************************
|
|
Common handler of wake-up pattern removal
|
|
***********************************************************/
|
|
NDIS_STATUS ParaNdis_OnRemoveWakeupPattern(PARANDIS_ADAPTER *pContext, tOidDesc *pOid)
|
|
{
|
|
NDIS_STATUS status;
|
|
PNDIS_PM_PACKET_PATTERN pPmPattern = (PNDIS_PM_PACKET_PATTERN) pOid->InformationBuffer;
|
|
ULONG ulValidSize = pOid->InformationBufferLength;
|
|
|
|
UNREFERENCED_PARAMETER(pContext);
|
|
|
|
status = ValidateWakeupPattern(pPmPattern, &ulValidSize);
|
|
if (status == NDIS_STATUS_SUCCESS)
|
|
{
|
|
*pOid->pBytesRead = ulValidSize;
|
|
}
|
|
else
|
|
{
|
|
*pOid->pBytesRead = 0;
|
|
*pOid->pBytesNeeded = ulValidSize;
|
|
}
|
|
return status;
|
|
}
|
|
|
|
/**********************************************************
|
|
Common handler of wake-up enabling upon standby
|
|
***********************************************************/
|
|
NDIS_STATUS ParaNdis_OnEnableWakeup(PARANDIS_ADAPTER *pContext, tOidDesc *pOid)
|
|
{
|
|
NDIS_STATUS status = ParaNdis_OidSetCopy(pOid, &pContext->ulEnableWakeup, sizeof(pContext->ulEnableWakeup));
|
|
if (status == NDIS_STATUS_SUCCESS)
|
|
{
|
|
DPrintf(0, "[%s] new value %lX\n", __FUNCTION__, pContext->ulEnableWakeup);
|
|
}
|
|
return status;
|
|
}
|
|
|
|
/**********************************************************
|
|
Dummy implementation
|
|
***********************************************************/
|
|
NDIS_STATUS ParaNdis_OnSetLookahead(PARANDIS_ADAPTER *pContext, tOidDesc *pOid)
|
|
{
|
|
return ParaNdis_OidSetCopy(pOid, &pContext->DummyLookAhead, sizeof(pContext->DummyLookAhead));
|
|
}
|
|
|
|
NDIS_STATUS ParaNdis_OnSetVlanId(PARANDIS_ADAPTER *pContext, tOidDesc *pOid)
|
|
{
|
|
NDIS_STATUS status = NDIS_STATUS_NOT_SUPPORTED;
|
|
if (IsVlanSupported(pContext))
|
|
{
|
|
status = ParaNdis_OidSetCopy(pOid, &pContext->VlanId, sizeof(pContext->VlanId));
|
|
pContext->VlanId &= 0xfff;
|
|
DPrintf(0, "[%s] new value %d on MAC %X\n", __FUNCTION__, pContext->VlanId, pContext->CurrentMacAddress[5]);
|
|
ParaNdis_DeviceFiltersUpdateVlanId(pContext);
|
|
}
|
|
return status;
|
|
}
|
|
|
|
/**********************************************************
|
|
Retrieves support rules for specific OID
|
|
***********************************************************/
|
|
void ParaNdis_GetOidSupportRules(NDIS_OID oid, tOidWhatToDo *pRule, const tOidWhatToDo *Table)
|
|
{
|
|
static const tOidWhatToDo defaultRule = { 0, 0, 0, 0, 0, NULL, "Unknown OID" };
|
|
UINT i;
|
|
*pRule = defaultRule;
|
|
pRule->oid = oid;
|
|
|
|
for (i = 0; Table[i].oid != 0; ++i)
|
|
{
|
|
if (Table[i].oid == oid)
|
|
{
|
|
*pRule = Table[i];
|
|
break;
|
|
}
|
|
}
|
|
pRule->name = ParaNdis_OidName(oid);
|
|
}
|