From 1ebe2ad920bce1f9ea85c56fce469674b83c650c Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Fri, 24 Apr 2015 23:31:51 -0700 Subject: NDIS6 driver with VS project to build -- builds correctly, not customized for ZT yet. --- windows/TapDriver6/oidrequest.c | 1028 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 1028 insertions(+) create mode 100644 windows/TapDriver6/oidrequest.c (limited to 'windows/TapDriver6/oidrequest.c') diff --git a/windows/TapDriver6/oidrequest.c b/windows/TapDriver6/oidrequest.c new file mode 100644 index 00000000..a6882f89 --- /dev/null +++ b/windows/TapDriver6/oidrequest.c @@ -0,0 +1,1028 @@ +/* + * TAP-Windows -- A kernel driver to provide virtual tap + * device functionality on Windows. + * + * This code was inspired by the CIPE-Win32 driver by Damion K. Wilson. + * + * This source code is Copyright (C) 2002-2014 OpenVPN Technologies, Inc., + * and is released under the GPL version 2 (see below). + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program (see the file COPYING included with this + * distribution); if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +// +// Include files. +// + +#include "tap.h" + +#ifndef DBG + +#define DBG_PRINT_OID_NAME + +#else + +VOID +DBG_PRINT_OID_NAME( + __in NDIS_OID Oid + ) +{ + PCHAR oidName = NULL; + + switch (Oid){ + + #undef MAKECASE + #define MAKECASE(oidx) case oidx: oidName = #oidx "\n"; break; + + /* Operational OIDs */ + 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_VENDOR_DRIVER_VERSION) + 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_MEDIA_CONNECT_STATUS) + MAKECASE(OID_GEN_MAXIMUM_SEND_PACKETS) + 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_MACHINE_NAME) + MAKECASE(OID_GEN_VLAN_ID) + MAKECASE(OID_GEN_RNDIS_CONFIG_PARAMETER) + + /* Operational OIDs for NDIS 6.0 */ + MAKECASE(OID_GEN_MAX_LINK_SPEED) + MAKECASE(OID_GEN_LINK_STATE) + MAKECASE(OID_GEN_LINK_PARAMETERS) + MAKECASE(OID_GEN_MINIPORT_RESTART_ATTRIBUTES) + MAKECASE(OID_GEN_ENUMERATE_PORTS) + MAKECASE(OID_GEN_PORT_STATE) + MAKECASE(OID_GEN_PORT_AUTHENTICATION_PARAMETERS) + MAKECASE(OID_GEN_INTERRUPT_MODERATION) + MAKECASE(OID_GEN_PHYSICAL_MEDIUM_EX) + + /* Statistical OIDs */ + 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) + + /* Statistical OIDs for NDIS 6.0 */ + MAKECASE(OID_GEN_STATISTICS) + MAKECASE(OID_GEN_BYTES_RCV) + MAKECASE(OID_GEN_BYTES_XMIT) + MAKECASE(OID_GEN_RCV_DISCARDS) + MAKECASE(OID_GEN_XMIT_DISCARDS) + + /* Misc OIDs */ + 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) + + /* PnP power management operational OIDs */ + 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_PNP_WAKE_UP_PATTERN_LIST) + + /* PnP power management statistical OIDs */ + MAKECASE(OID_PNP_WAKE_UP_ERROR) + MAKECASE(OID_PNP_WAKE_UP_OK) + + /* Ethernet operational OIDs */ + 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) + + /* Ethernet operational OIDs for NDIS 6.0 */ + MAKECASE(OID_802_3_ADD_MULTICAST_ADDRESS) + MAKECASE(OID_802_3_DELETE_MULTICAST_ADDRESS) + + /* Ethernet statistical OIDs */ + 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) + + /* TCP/IP OIDs */ + MAKECASE(OID_TCP_TASK_OFFLOAD) + MAKECASE(OID_TCP_TASK_IPSEC_ADD_SA) + MAKECASE(OID_TCP_TASK_IPSEC_DELETE_SA) + MAKECASE(OID_TCP_SAN_SUPPORT) + MAKECASE(OID_TCP_TASK_IPSEC_ADD_UDPESP_SA) + MAKECASE(OID_TCP_TASK_IPSEC_DELETE_UDPESP_SA) + MAKECASE(OID_TCP4_OFFLOAD_STATS) + MAKECASE(OID_TCP6_OFFLOAD_STATS) + MAKECASE(OID_IP4_OFFLOAD_STATS) + MAKECASE(OID_IP6_OFFLOAD_STATS) + + /* TCP offload OIDs for NDIS 6 */ + MAKECASE(OID_TCP_OFFLOAD_CURRENT_CONFIG) + MAKECASE(OID_TCP_OFFLOAD_PARAMETERS) + MAKECASE(OID_TCP_OFFLOAD_HARDWARE_CAPABILITIES) + MAKECASE(OID_TCP_CONNECTION_OFFLOAD_CURRENT_CONFIG) + MAKECASE(OID_TCP_CONNECTION_OFFLOAD_HARDWARE_CAPABILITIES) + MAKECASE(OID_OFFLOAD_ENCAPSULATION) + +#if (NDIS_SUPPORT_NDIS620) + /* VMQ OIDs for NDIS 6.20 */ + MAKECASE(OID_RECEIVE_FILTER_FREE_QUEUE) + MAKECASE(OID_RECEIVE_FILTER_CLEAR_FILTER) + MAKECASE(OID_RECEIVE_FILTER_ALLOCATE_QUEUE) + MAKECASE(OID_RECEIVE_FILTER_QUEUE_ALLOCATION_COMPLETE) + MAKECASE(OID_RECEIVE_FILTER_SET_FILTER) +#endif + +#if (NDIS_SUPPORT_NDIS630) + /* NDIS QoS OIDs for NDIS 6.30 */ + MAKECASE(OID_QOS_PARAMETERS) +#endif + } + + if (oidName) + { + DEBUGP(("OID: %s", oidName)); + } + else + { + DEBUGP(("<** Unknown OID 0x%08x **>\n", Oid)); + } +} + +#endif // DBG + +//====================================================================== +// TAP NDIS 6 OID Request Callbacks +//====================================================================== + +NDIS_STATUS +tapSetMulticastList( + __in PTAP_ADAPTER_CONTEXT Adapter, + __in PNDIS_OID_REQUEST OidRequest + ) +{ + NDIS_STATUS status = NDIS_STATUS_SUCCESS; + + // + // Initialize. + // + OidRequest->DATA.SET_INFORMATION.BytesNeeded = MACADDR_SIZE; + OidRequest->DATA.SET_INFORMATION.BytesRead + = OidRequest->DATA.SET_INFORMATION.InformationBufferLength; + + + do + { + if (OidRequest->DATA.SET_INFORMATION.InformationBufferLength % MACADDR_SIZE) + { + status = NDIS_STATUS_INVALID_LENGTH; + break; + } + + if (OidRequest->DATA.SET_INFORMATION.InformationBufferLength > (TAP_MAX_MCAST_LIST * MACADDR_SIZE)) + { + status = NDIS_STATUS_MULTICAST_FULL; + OidRequest->DATA.SET_INFORMATION.BytesNeeded = TAP_MAX_MCAST_LIST * MACADDR_SIZE; + break; + } + + // BUGBUG!!! Is lock needed??? If so, use NDIS_RW_LOCK. Also apply to packet filter. + + NdisZeroMemory(Adapter->MCList, + TAP_MAX_MCAST_LIST * MACADDR_SIZE); + + NdisMoveMemory(Adapter->MCList, + OidRequest->DATA.SET_INFORMATION.InformationBuffer, + OidRequest->DATA.SET_INFORMATION.InformationBufferLength); + + Adapter->ulMCListSize = OidRequest->DATA.SET_INFORMATION.InformationBufferLength / MACADDR_SIZE; + + } while(FALSE); + return status; +} + +NDIS_STATUS +tapSetPacketFilter( + __in PTAP_ADAPTER_CONTEXT Adapter, + __in ULONG PacketFilter + ) +{ + NDIS_STATUS status = NDIS_STATUS_SUCCESS; + + // any bits not supported? + if (PacketFilter & ~(TAP_SUPPORTED_FILTERS)) + { + DEBUGP (("[TAP] Unsupported packet filter: 0x%08x\n", PacketFilter)); + status = NDIS_STATUS_NOT_SUPPORTED; + } + else + { + // Any actual filtering changes? + if (PacketFilter != Adapter->PacketFilter) + { + // + // Change the filtering modes on hardware + // + + // Save the new packet filter value + Adapter->PacketFilter = PacketFilter; + } + } + + return status; +} + +NDIS_STATUS +AdapterSetPowerD0( + __in PTAP_ADAPTER_CONTEXT Adapter + ) +/*++ +Routine Description: + + NIC power has been restored to the working power state (D0). + Prepare the NIC for normal operation: + - Restore hardware context (packet filters, multicast addresses, MAC address, etc.) + - Enable interrupts and the NIC's DMA engine. + +Arguments: + + Adapter - Pointer to adapter block + +Return Value: + + NDIS_STATUS + +--*/ +{ + NDIS_STATUS status = NDIS_STATUS_SUCCESS; + + DEBUGP (("[TAP] PowerState: Fully powered\n")); + + // Start data path... + + return status; +} + +NDIS_STATUS +AdapterSetPowerLow( + __in PTAP_ADAPTER_CONTEXT Adapter, + __in NDIS_DEVICE_POWER_STATE PowerState + ) +/*++ +Routine Description: + + The NIC is about to be transitioned to a low power state. + Prepare the NIC for the sleeping state: + - Disable interrupts and the NIC's DMA engine, cancel timers. + - Save any hardware context that the NIC cannot preserve in + a sleeping state (packet filters, multicast addresses, + the current MAC address, etc.) + A miniport driver cannot access the NIC hardware after + the NIC has been set to the D3 state by the bus driver. + + Miniport drivers NDIS v6.30 and above + Do NOT wait for NDIS to return the ownership of all + NBLs from outstanding receive indications + Retain ownership of all the receive descriptors and + packet buffers previously owned by the hardware. + +Arguments: + + Adapter - Pointer to adapter block + PowerState - New power state + +Return Value: + + NDIS_STATUS + +--*/ +{ + NDIS_STATUS status = NDIS_STATUS_SUCCESS; + + DEBUGP (("[TAP] PowerState: Low-power\n")); + + // + // Miniport drivers NDIS v6.20 and below are + // paused prior the low power transition + // + + // Check for paused state... + // Verify data path stopped... + + return status; +} + +NDIS_STATUS +tapSetInformation( + __in PTAP_ADAPTER_CONTEXT Adapter, + __in PNDIS_OID_REQUEST OidRequest + ) +/*++ + +Routine Description: + + Helper function to perform a set OID request + +Arguments: + + Adapter - + NdisSetRequest - The OID to set + +Return Value: + + NDIS_STATUS + +--*/ +{ + NDIS_STATUS status = NDIS_STATUS_SUCCESS; + + DBG_PRINT_OID_NAME(OidRequest->DATA.SET_INFORMATION.Oid); + + switch(OidRequest->DATA.SET_INFORMATION.Oid) + { + case OID_802_3_MULTICAST_LIST: + // + // Set the multicast address list on the NIC for packet reception. + // The NIC driver can set a limit on the number of multicast + // addresses bound protocol drivers can enable simultaneously. + // NDIS returns NDIS_STATUS_MULTICAST_FULL if a protocol driver + // exceeds this limit or if it specifies an invalid multicast + // address. + // + status = tapSetMulticastList(Adapter,OidRequest); + break; + + case OID_GEN_CURRENT_LOOKAHEAD: + // + // A protocol driver can set a suggested value for the number + // of bytes to be used in its binding; however, the underlying + // NIC driver is never required to limit its indications to + // the value set. + // + if (OidRequest->DATA.SET_INFORMATION.InformationBufferLength != sizeof(ULONG)) + { + OidRequest->DATA.SET_INFORMATION.BytesNeeded = sizeof(ULONG); + status = NDIS_STATUS_INVALID_LENGTH; + break; + } + + Adapter->ulLookahead = *(PULONG)OidRequest->DATA.SET_INFORMATION.InformationBuffer; + + OidRequest->DATA.SET_INFORMATION.BytesRead = sizeof(ULONG); + status = NDIS_STATUS_SUCCESS; + break; + + case OID_GEN_CURRENT_PACKET_FILTER: + // + // Program the hardware to indicate the packets + // of certain filter types. + // + if(OidRequest->DATA.SET_INFORMATION.InformationBufferLength != sizeof(ULONG)) + { + OidRequest->DATA.SET_INFORMATION.BytesNeeded = sizeof(ULONG); + status = NDIS_STATUS_INVALID_LENGTH; + break; + } + + OidRequest->DATA.SET_INFORMATION.BytesRead + = OidRequest->DATA.SET_INFORMATION.InformationBufferLength; + + status = tapSetPacketFilter( + Adapter, + *((PULONG)OidRequest->DATA.SET_INFORMATION.InformationBuffer) + ); + + break; + + case OID_PNP_SET_POWER: + { + // Sanity check. + if (OidRequest->DATA.SET_INFORMATION.InformationBufferLength + < sizeof(NDIS_DEVICE_POWER_STATE) + ) + { + status = NDIS_STATUS_INVALID_LENGTH; + } + else + { + NDIS_DEVICE_POWER_STATE PowerState; + + PowerState = *(PNDIS_DEVICE_POWER_STATE UNALIGNED)OidRequest->DATA.SET_INFORMATION.InformationBuffer; + OidRequest->DATA.SET_INFORMATION.BytesRead = sizeof(NDIS_DEVICE_POWER_STATE); + + if(PowerState < NdisDeviceStateD0 || + PowerState > NdisDeviceStateD3) + { + status = NDIS_STATUS_INVALID_DATA; + } + else + { + Adapter->CurrentPowerState = PowerState; + + if (PowerState == NdisDeviceStateD0) + { + status = AdapterSetPowerD0(Adapter); + } + else + { + status = AdapterSetPowerLow(Adapter, PowerState); + } + } + } + } + break; + +#if (NDIS_SUPPORT_NDIS61) + case OID_PNP_ADD_WAKE_UP_PATTERN: + case OID_PNP_REMOVE_WAKE_UP_PATTERN: + case OID_PNP_ENABLE_WAKE_UP: +#endif + ASSERT(!"NIC does not support wake on LAN OIDs"); + default: + // + // The entry point may by used by other requests + // + status = NDIS_STATUS_NOT_SUPPORTED; + break; + } + + return status; +} + +NDIS_STATUS +tapQueryInformation( + __in PTAP_ADAPTER_CONTEXT Adapter, + __in PNDIS_OID_REQUEST OidRequest + ) +/*++ + +Routine Description: + + Helper function to perform a query OID request + +Arguments: + + Adapter - + OidRequest - The OID request that is being queried + +Return Value: + + NDIS_STATUS + +--*/ +{ + NDIS_STATUS status = NDIS_STATUS_SUCCESS; + NDIS_MEDIUM Medium = TAP_MEDIUM_TYPE; + NDIS_HARDWARE_STATUS HardwareStatus = NdisHardwareStatusReady; + UCHAR VendorDesc[] = TAP_VENDOR_DESC; + ULONG ulInfo; + USHORT usInfo; + ULONG64 ulInfo64; + + // Default to returning the ULONG value + PVOID pInfo=NULL; + ULONG ulInfoLen = sizeof(ulInfo); + + // ATTENTION!!! Ignore OIDs to noisy to print... + if((OidRequest->DATA.QUERY_INFORMATION.Oid != OID_GEN_STATISTICS) + && (OidRequest->DATA.QUERY_INFORMATION.Oid != OID_IP4_OFFLOAD_STATS) + && (OidRequest->DATA.QUERY_INFORMATION.Oid != OID_IP6_OFFLOAD_STATS) + ) + { + DBG_PRINT_OID_NAME(OidRequest->DATA.QUERY_INFORMATION.Oid); + } + + // Dispatch based on object identifier (OID). + switch(OidRequest->DATA.QUERY_INFORMATION.Oid) + { + case OID_GEN_HARDWARE_STATUS: + // + // Specify the current hardware status of the underlying NIC as + // one of the following NDIS_HARDWARE_STATUS-type values. + // + pInfo = (PVOID) &HardwareStatus; + ulInfoLen = sizeof(NDIS_HARDWARE_STATUS); + break; + + case OID_802_3_PERMANENT_ADDRESS: + // + // Return the MAC address of the NIC burnt in the hardware. + // + pInfo = Adapter->PermanentAddress; + ulInfoLen = MACADDR_SIZE; + break; + + case OID_802_3_CURRENT_ADDRESS: + // + // Return the MAC address the NIC is currently programmed to + // use. Note that this address could be different from the + // permananent address as the user can override using + // registry. Read NdisReadNetworkAddress doc for more info. + // + pInfo = Adapter->CurrentAddress; + ulInfoLen = MACADDR_SIZE; + break; + + case OID_GEN_MEDIA_SUPPORTED: + // + // Return an array of media that are supported by the miniport. + // This miniport only supports one medium (Ethernet), so the OID + // returns identical results to OID_GEN_MEDIA_IN_USE. + // + + __fallthrough; + + case OID_GEN_MEDIA_IN_USE: + // + // Return an array of media that are currently in use by the + // miniport. This array should be a subset of the array returned + // by OID_GEN_MEDIA_SUPPORTED. + // + pInfo = &Medium; + ulInfoLen = sizeof(Medium); + break; + + case OID_GEN_MAXIMUM_TOTAL_SIZE: + // + // Specify the maximum total packet length, in bytes, the NIC + // supports including the header. A protocol driver might use + // this returned length as a gauge to determine the maximum + // size packet that a NIC driver could forward to the + // protocol driver. The miniport driver must never indicate + // up to the bound protocol driver packets received over the + // network that are longer than the packet size specified by + // OID_GEN_MAXIMUM_TOTAL_SIZE. + // + + __fallthrough; + + case OID_GEN_TRANSMIT_BLOCK_SIZE: + // + // The OID_GEN_TRANSMIT_BLOCK_SIZE OID specifies the minimum + // number of bytes that a single net packet occupies in the + // transmit buffer space of the NIC. In our case, the transmit + // block size is identical to its maximum packet size. + __fallthrough; + + case OID_GEN_RECEIVE_BLOCK_SIZE: + // + // The OID_GEN_RECEIVE_BLOCK_SIZE OID specifies the amount of + // storage, in bytes, that a single packet occupies in the receive + // buffer space of the NIC. + // + ulInfo = (ULONG) TAP_MAX_FRAME_SIZE; + pInfo = &ulInfo; + break; + + case OID_GEN_INTERRUPT_MODERATION: + { + PNDIS_INTERRUPT_MODERATION_PARAMETERS moderationParams + = (PNDIS_INTERRUPT_MODERATION_PARAMETERS)OidRequest->DATA.QUERY_INFORMATION.InformationBuffer; + + moderationParams->Header.Type = NDIS_OBJECT_TYPE_DEFAULT; + moderationParams->Header.Revision = NDIS_INTERRUPT_MODERATION_PARAMETERS_REVISION_1; + moderationParams->Header.Size = NDIS_SIZEOF_INTERRUPT_MODERATION_PARAMETERS_REVISION_1; + moderationParams->Flags = 0; + moderationParams->InterruptModeration = NdisInterruptModerationNotSupported; + ulInfoLen = NDIS_SIZEOF_INTERRUPT_MODERATION_PARAMETERS_REVISION_1; + } + break; + + case OID_PNP_QUERY_POWER: + // Simply succeed this. + break; + + case OID_GEN_VENDOR_ID: + // + // Specify a three-byte IEEE-registered vendor code, followed + // by a single byte that the vendor assigns to identify a + // particular NIC. The IEEE code uniquely identifies the vendor + // and is the same as the three bytes appearing at the beginning + // of the NIC hardware address. Vendors without an IEEE-registered + // code should use the value 0xFFFFFF. + // + + ulInfo = TAP_VENDOR_ID; + pInfo = &ulInfo; + break; + + case OID_GEN_VENDOR_DESCRIPTION: + // + // Specify a zero-terminated string describing the NIC vendor. + // + pInfo = VendorDesc; + ulInfoLen = sizeof(VendorDesc); + break; + + case OID_GEN_VENDOR_DRIVER_VERSION: + // + // Specify the vendor-assigned version number of the NIC driver. + // The low-order half of the return value specifies the minor + // version; the high-order half specifies the major version. + // + + ulInfo = TAP_DRIVER_VENDOR_VERSION; + pInfo = &ulInfo; + break; + + case OID_GEN_DRIVER_VERSION: + // + // Specify the NDIS version in use by the NIC driver. The high + // byte is the major version number; the low byte is the minor + // version number. + // + usInfo = (USHORT) (TAP_NDIS_MAJOR_VERSION<<8) + TAP_NDIS_MINOR_VERSION; + pInfo = (PVOID) &usInfo; + ulInfoLen = sizeof(USHORT); + break; + + case OID_802_3_MAXIMUM_LIST_SIZE: + // + // The maximum number of multicast addresses the NIC driver + // can manage. This list is global for all protocols bound + // to (or above) the NIC. Consequently, a protocol can receive + // NDIS_STATUS_MULTICAST_FULL from the NIC driver when + // attempting to set the multicast address list, even if + // the number of elements in the given list is less than + // the number originally returned for this query. + // + + ulInfo = TAP_MAX_MCAST_LIST; + pInfo = &ulInfo; + break; + + case OID_GEN_XMIT_ERROR: + ulInfo = (ULONG) + (Adapter->TxAbortExcessCollisions + + Adapter->TxDmaUnderrun + + Adapter->TxLostCRS + + Adapter->TxLateCollisions+ + Adapter->TransmitFailuresOther); + pInfo = &ulInfo; + break; + + case OID_GEN_RCV_ERROR: + ulInfo = (ULONG) + (Adapter->RxCrcErrors + + Adapter->RxAlignmentErrors + + Adapter->RxDmaOverrunErrors + + Adapter->RxRuntErrors); + pInfo = &ulInfo; + break; + + case OID_GEN_RCV_DISCARDS: + ulInfo = (ULONG)Adapter->RxResourceErrors; + pInfo = &ulInfo; + break; + + case OID_GEN_RCV_NO_BUFFER: + ulInfo = (ULONG)Adapter->RxResourceErrors; + pInfo = &ulInfo; + break; + + case OID_GEN_XMIT_OK: + ulInfo64 = Adapter->FramesTxBroadcast + + Adapter->FramesTxMulticast + + Adapter->FramesTxDirected; + pInfo = &ulInfo64; + if (OidRequest->DATA.QUERY_INFORMATION.InformationBufferLength >= sizeof(ULONG64) || + OidRequest->DATA.QUERY_INFORMATION.InformationBufferLength == 0) + { + ulInfoLen = sizeof(ULONG64); + } + else + { + ulInfoLen = sizeof(ULONG); + } + + // We should always report that only 8 bytes are required to keep ndistest happy + OidRequest->DATA.QUERY_INFORMATION.BytesNeeded = sizeof(ULONG64); + break; + + case OID_GEN_RCV_OK: + ulInfo64 = Adapter->FramesRxBroadcast + + Adapter->FramesRxMulticast + + Adapter->FramesRxDirected; + + pInfo = &ulInfo64; + + if (OidRequest->DATA.QUERY_INFORMATION.InformationBufferLength >= sizeof(ULONG64) || + OidRequest->DATA.QUERY_INFORMATION.InformationBufferLength == 0) + { + ulInfoLen = sizeof(ULONG64); + } + else + { + ulInfoLen = sizeof(ULONG); + } + + // We should always report that only 8 bytes are required to keep ndistest happy + OidRequest->DATA.QUERY_INFORMATION.BytesNeeded = sizeof(ULONG64); + break; + + case OID_802_3_RCV_ERROR_ALIGNMENT: + + ulInfo = Adapter->RxAlignmentErrors; + pInfo = &ulInfo; + break; + + case OID_802_3_XMIT_ONE_COLLISION: + + ulInfo = Adapter->OneRetry; + pInfo = &ulInfo; + break; + + case OID_802_3_XMIT_MORE_COLLISIONS: + + ulInfo = Adapter->MoreThanOneRetry; + pInfo = &ulInfo; + break; + + case OID_802_3_XMIT_DEFERRED: + + ulInfo = Adapter->TxOKButDeferred; + pInfo = &ulInfo; + break; + + case OID_802_3_XMIT_MAX_COLLISIONS: + + ulInfo = Adapter->TxAbortExcessCollisions; + pInfo = &ulInfo; + break; + + case OID_802_3_RCV_OVERRUN: + + ulInfo = Adapter->RxDmaOverrunErrors; + pInfo = &ulInfo; + break; + + case OID_802_3_XMIT_UNDERRUN: + + ulInfo = Adapter->TxDmaUnderrun; + pInfo = &ulInfo; + break; + + case OID_GEN_STATISTICS: + + if (OidRequest->DATA.QUERY_INFORMATION.InformationBufferLength < sizeof(NDIS_STATISTICS_INFO)) + { + status = NDIS_STATUS_INVALID_LENGTH; + OidRequest->DATA.QUERY_INFORMATION.BytesNeeded = sizeof(NDIS_STATISTICS_INFO); + break; + } + else + { + PNDIS_STATISTICS_INFO Statistics + = (PNDIS_STATISTICS_INFO)OidRequest->DATA.QUERY_INFORMATION.InformationBuffer; + + {C_ASSERT(sizeof(NDIS_STATISTICS_INFO) >= NDIS_SIZEOF_STATISTICS_INFO_REVISION_1);} + Statistics->Header.Type = NDIS_OBJECT_TYPE_DEFAULT; + Statistics->Header.Size = NDIS_SIZEOF_STATISTICS_INFO_REVISION_1; + Statistics->Header.Revision = NDIS_STATISTICS_INFO_REVISION_1; + + Statistics->SupportedStatistics = TAP_SUPPORTED_STATISTICS; + + /* Bytes in */ + Statistics->ifHCInOctets = + Adapter->BytesRxDirected + + Adapter->BytesRxMulticast + + Adapter->BytesRxBroadcast; + + Statistics->ifHCInUcastOctets = + Adapter->BytesRxDirected; + + Statistics->ifHCInMulticastOctets = + Adapter->BytesRxMulticast; + + Statistics->ifHCInBroadcastOctets = + Adapter->BytesRxBroadcast; + + /* Packets in */ + Statistics->ifHCInUcastPkts = + Adapter->FramesRxDirected; + + Statistics->ifHCInMulticastPkts = + Adapter->FramesRxMulticast; + + Statistics->ifHCInBroadcastPkts = + Adapter->FramesRxBroadcast; + + /* Errors in */ + Statistics->ifInErrors = + Adapter->RxCrcErrors + + Adapter->RxAlignmentErrors + + Adapter->RxDmaOverrunErrors + + Adapter->RxRuntErrors; + + Statistics->ifInDiscards = + Adapter->RxResourceErrors; + + + /* Bytes out */ + Statistics->ifHCOutOctets = + Adapter->BytesTxDirected + + Adapter->BytesTxMulticast + + Adapter->BytesTxBroadcast; + + Statistics->ifHCOutUcastOctets = + Adapter->BytesTxDirected; + + Statistics->ifHCOutMulticastOctets = + Adapter->BytesTxMulticast; + + Statistics->ifHCOutBroadcastOctets = + Adapter->BytesTxBroadcast; + + /* Packets out */ + Statistics->ifHCOutUcastPkts = + Adapter->FramesTxDirected; + + Statistics->ifHCOutMulticastPkts = + Adapter->FramesTxMulticast; + + Statistics->ifHCOutBroadcastPkts = + Adapter->FramesTxBroadcast; + + /* Errors out */ + Statistics->ifOutErrors = + Adapter->TxAbortExcessCollisions + + Adapter->TxDmaUnderrun + + Adapter->TxLostCRS + + Adapter->TxLateCollisions+ + Adapter->TransmitFailuresOther; + + Statistics->ifOutDiscards = 0ULL; + + ulInfoLen = NDIS_SIZEOF_STATISTICS_INFO_REVISION_1; + } + + break; + + // TODO: Inplement these query information requests. + case OID_GEN_RECEIVE_BUFFER_SPACE: + case OID_GEN_MAXIMUM_SEND_PACKETS: + case OID_GEN_TRANSMIT_QUEUE_LENGTH: + case OID_802_3_XMIT_HEARTBEAT_FAILURE: + case OID_802_3_XMIT_TIMES_CRS_LOST: + case OID_802_3_XMIT_LATE_COLLISIONS: + + default: + // + // The entry point may by used by other requests + // + status = NDIS_STATUS_NOT_SUPPORTED; + break; + } + + if (status == NDIS_STATUS_SUCCESS) + { + ASSERT(ulInfoLen > 0); + + if (ulInfoLen <= OidRequest->DATA.QUERY_INFORMATION.InformationBufferLength) + { + if(pInfo) + { + // Copy result into InformationBuffer + NdisMoveMemory( + OidRequest->DATA.QUERY_INFORMATION.InformationBuffer, + pInfo, + ulInfoLen + ); + } + + OidRequest->DATA.QUERY_INFORMATION.BytesWritten = ulInfoLen; + } + else + { + // too short + OidRequest->DATA.QUERY_INFORMATION.BytesNeeded = ulInfoLen; + status = NDIS_STATUS_BUFFER_TOO_SHORT; + } + } + + return status; +} + +NDIS_STATUS +AdapterOidRequest( + __in NDIS_HANDLE MiniportAdapterContext, + __in PNDIS_OID_REQUEST OidRequest + ) +/*++ + +Routine Description: + + Entry point called by NDIS to get or set the value of a specified OID. + +Arguments: + + MiniportAdapterContext - Our adapter handle + NdisRequest - The OID request to handle + +Return Value: + + Return code from the NdisRequest below. + +--*/ +{ + PTAP_ADAPTER_CONTEXT adapter = (PTAP_ADAPTER_CONTEXT )MiniportAdapterContext; + NDIS_STATUS status; + + // Dispatch based on request type. + switch (OidRequest->RequestType) + { + case NdisRequestSetInformation: + status = tapSetInformation(adapter,OidRequest); + break; + + case NdisRequestQueryInformation: + case NdisRequestQueryStatistics: + status = tapQueryInformation(adapter,OidRequest); + break; + + case NdisRequestMethod: // TAP doesn't need to respond to this request type. + default: + // + // The entry point may by used by other requests + // + status = NDIS_STATUS_NOT_SUPPORTED; + break; + } + + return status; +} + +VOID +AdapterCancelOidRequest( + __in NDIS_HANDLE MiniportAdapterContext, + __in PVOID RequestId + ) +{ + PTAP_ADAPTER_CONTEXT adapter = (PTAP_ADAPTER_CONTEXT )MiniportAdapterContext; + + UNREFERENCED_PARAMETER(RequestId); + + // + // This miniport sample does not pend any OID requests, so we don't have + // to worry about cancelling them. + // +} + -- cgit v1.2.3