Upgrade OID_GEN_XMIT_OK and OID_GEN_RCV_OK to support 64-bit counters

This commit addresses issues reported by NDISTEST/1c_64bitoids.

It also revises the OID request writing, as adaptive 32/64-bit responses
required by OID_GEN_XMIT_OK and OID_GEN_RCV_OK would grow the current
TunOidQuery() design quite complex and introduce duplicated code.

Signed-off-by: Simon Rozman <simon@rozman.si>
This commit is contained in:
Simon Rozman 2019-04-05 11:04:13 +02:00
parent 1c13736068
commit bf48214c8c

110
wintun.c
View File

@ -1214,8 +1214,8 @@ static NDIS_STATUS TunOidSet(_Inout_ TUN_CTX *ctx, _Inout_ NDIS_OID_REQUEST *Oid
{ {
ASSERT(OidRequest->RequestType == NdisRequestSetInformation); ASSERT(OidRequest->RequestType == NdisRequestSetInformation);
OidRequest->DATA.SET_INFORMATION.BytesNeeded =
OidRequest->DATA.SET_INFORMATION.BytesRead = 0; OidRequest->DATA.SET_INFORMATION.BytesRead = 0;
OidRequest->DATA.SET_INFORMATION.BytesNeeded = 0;
switch (OidRequest->DATA.SET_INFORMATION.Oid) { switch (OidRequest->DATA.SET_INFORMATION.Oid) {
case OID_GEN_CURRENT_PACKET_FILTER: case OID_GEN_CURRENT_PACKET_FILTER:
@ -1247,59 +1247,100 @@ static NDIS_STATUS TunOidSet(_Inout_ TUN_CTX *ctx, _Inout_ NDIS_OID_REQUEST *Oid
return NDIS_STATUS_INVALID_OID; return NDIS_STATUS_INVALID_OID;
} }
_IRQL_requires_max_(APC_LEVEL)
_Must_inspect_result_
static NDIS_STATUS TunOidQueryWrite(_Inout_ NDIS_OID_REQUEST *OidRequest, _In_ ULONG value)
{
if (OidRequest->DATA.QUERY_INFORMATION.InformationBufferLength < sizeof(ULONG)) {
OidRequest->DATA.QUERY_INFORMATION.BytesNeeded = sizeof(ULONG);
OidRequest->DATA.QUERY_INFORMATION.BytesWritten = 0;
return NDIS_STATUS_INVALID_LENGTH;
}
OidRequest->DATA.QUERY_INFORMATION.BytesNeeded =
OidRequest->DATA.QUERY_INFORMATION.BytesWritten = sizeof(ULONG);
*(ULONG *)OidRequest->DATA.QUERY_INFORMATION.InformationBuffer = value;
return NDIS_STATUS_SUCCESS;
}
_IRQL_requires_max_(APC_LEVEL)
_Must_inspect_result_
static NDIS_STATUS TunOidQueryWrite32or64(_Inout_ NDIS_OID_REQUEST *OidRequest, _In_ ULONG64 value)
{
if (OidRequest->DATA.QUERY_INFORMATION.InformationBufferLength < sizeof(ULONG)) {
OidRequest->DATA.QUERY_INFORMATION.BytesNeeded = sizeof(ULONG64);
OidRequest->DATA.QUERY_INFORMATION.BytesWritten = 0;
return NDIS_STATUS_INVALID_LENGTH;
}
if (OidRequest->DATA.QUERY_INFORMATION.InformationBufferLength < sizeof(ULONG64)) {
OidRequest->DATA.QUERY_INFORMATION.BytesNeeded = sizeof(ULONG64);
OidRequest->DATA.QUERY_INFORMATION.BytesWritten = sizeof(ULONG);
*(ULONG *)OidRequest->DATA.QUERY_INFORMATION.InformationBuffer = (ULONG)(value & 0xffffffff);
return NDIS_STATUS_SUCCESS;
}
OidRequest->DATA.QUERY_INFORMATION.BytesNeeded =
OidRequest->DATA.QUERY_INFORMATION.BytesWritten = sizeof(ULONG64);
*(ULONG64 *)OidRequest->DATA.QUERY_INFORMATION.InformationBuffer = value;
return NDIS_STATUS_SUCCESS;
}
_IRQL_requires_max_(APC_LEVEL)
_Must_inspect_result_
static NDIS_STATUS TunOidQueryWriteBuf(_Inout_ NDIS_OID_REQUEST *OidRequest, _In_bytecount_(size) const void *buf, _In_ UINT size)
{
if (OidRequest->DATA.QUERY_INFORMATION.InformationBufferLength < size) {
OidRequest->DATA.QUERY_INFORMATION.BytesNeeded = size;
OidRequest->DATA.QUERY_INFORMATION.BytesWritten = 0;
return NDIS_STATUS_INVALID_LENGTH;
}
OidRequest->DATA.QUERY_INFORMATION.BytesNeeded =
OidRequest->DATA.QUERY_INFORMATION.BytesWritten = size;
NdisMoveMemory(OidRequest->DATA.QUERY_INFORMATION.InformationBuffer, buf, size);
return NDIS_STATUS_SUCCESS;
}
_IRQL_requires_max_(APC_LEVEL) _IRQL_requires_max_(APC_LEVEL)
_Must_inspect_result_ _Must_inspect_result_
static NDIS_STATUS TunOidQuery(_Inout_ TUN_CTX *ctx, _Inout_ NDIS_OID_REQUEST *OidRequest) static NDIS_STATUS TunOidQuery(_Inout_ TUN_CTX *ctx, _Inout_ NDIS_OID_REQUEST *OidRequest)
{ {
ASSERT(OidRequest->RequestType == NdisRequestQueryInformation || OidRequest->RequestType == NdisRequestQueryStatistics); ASSERT(OidRequest->RequestType == NdisRequestQueryInformation || OidRequest->RequestType == NdisRequestQueryStatistics);
UINT value32;
UINT size = sizeof(value32);
const void *buf = &value32;
switch (OidRequest->DATA.QUERY_INFORMATION.Oid) { switch (OidRequest->DATA.QUERY_INFORMATION.Oid) {
case OID_GEN_MAXIMUM_TOTAL_SIZE: case OID_GEN_MAXIMUM_TOTAL_SIZE:
case OID_GEN_TRANSMIT_BLOCK_SIZE: case OID_GEN_TRANSMIT_BLOCK_SIZE:
case OID_GEN_RECEIVE_BLOCK_SIZE: case OID_GEN_RECEIVE_BLOCK_SIZE:
value32 = TUN_EXCH_MAX_IP_PACKET_SIZE; return TunOidQueryWrite(OidRequest, TUN_EXCH_MAX_IP_PACKET_SIZE);
break;
case OID_GEN_TRANSMIT_BUFFER_SPACE: case OID_GEN_TRANSMIT_BUFFER_SPACE:
case OID_GEN_RECEIVE_BUFFER_SPACE: case OID_GEN_RECEIVE_BUFFER_SPACE:
value32 = TUN_EXCH_MAX_IP_PACKET_SIZE * TUN_EXCH_MAX_PACKETS; return TunOidQueryWrite(OidRequest, TUN_EXCH_MAX_IP_PACKET_SIZE * TUN_EXCH_MAX_PACKETS);
break;
case OID_GEN_VENDOR_ID: case OID_GEN_VENDOR_ID:
value32 = TunHtonl(TUN_VENDOR_ID); return TunOidQueryWrite(OidRequest, TunHtonl(TUN_VENDOR_ID));
break;
case OID_GEN_VENDOR_DESCRIPTION: case OID_GEN_VENDOR_DESCRIPTION:
size = (UINT)sizeof(TUN_VENDOR_NAME); return TunOidQueryWriteBuf(OidRequest, TUN_VENDOR_NAME, (UINT)sizeof(TUN_VENDOR_NAME));
buf = TUN_VENDOR_NAME;
break;
case OID_GEN_VENDOR_DRIVER_VERSION: case OID_GEN_VENDOR_DRIVER_VERSION:
value32 = (WINTUN_VERSION_MAJ << 16) | WINTUN_VERSION_MIN; return TunOidQueryWrite(OidRequest, (WINTUN_VERSION_MAJ << 16) | WINTUN_VERSION_MIN);
break;
case OID_GEN_XMIT_OK: case OID_GEN_XMIT_OK:
value32 = (UINT)( return TunOidQueryWrite32or64(OidRequest,
InterlockedGet64((LONG64 *)&ctx->Statistics.ifHCOutUcastPkts ) + InterlockedGet64((LONG64 *)&ctx->Statistics.ifHCOutUcastPkts ) +
InterlockedGet64((LONG64 *)&ctx->Statistics.ifHCOutMulticastPkts) + InterlockedGet64((LONG64 *)&ctx->Statistics.ifHCOutMulticastPkts) +
InterlockedGet64((LONG64 *)&ctx->Statistics.ifHCOutBroadcastPkts)); InterlockedGet64((LONG64 *)&ctx->Statistics.ifHCOutBroadcastPkts));
break;
case OID_GEN_RCV_OK: case OID_GEN_RCV_OK:
value32 = (UINT)( return TunOidQueryWrite32or64(OidRequest,
InterlockedGet64((LONG64 *)&ctx->Statistics.ifHCInUcastPkts ) + InterlockedGet64((LONG64 *)&ctx->Statistics.ifHCInUcastPkts ) +
InterlockedGet64((LONG64 *)&ctx->Statistics.ifHCInMulticastPkts) + InterlockedGet64((LONG64 *)&ctx->Statistics.ifHCInMulticastPkts) +
InterlockedGet64((LONG64 *)&ctx->Statistics.ifHCInBroadcastPkts)); InterlockedGet64((LONG64 *)&ctx->Statistics.ifHCInBroadcastPkts));
break;
case OID_GEN_STATISTICS: case OID_GEN_STATISTICS:
size = (UINT)sizeof(ctx->Statistics); return TunOidQueryWriteBuf(OidRequest, &ctx->Statistics, (UINT)sizeof(ctx->Statistics));
buf = &ctx->Statistics;
break;
case OID_GEN_INTERRUPT_MODERATION: { case OID_GEN_INTERRUPT_MODERATION: {
static const NDIS_INTERRUPT_MODERATION_PARAMETERS intp = { static const NDIS_INTERRUPT_MODERATION_PARAMETERS intp = {
@ -1310,32 +1351,19 @@ static NDIS_STATUS TunOidQuery(_Inout_ TUN_CTX *ctx, _Inout_ NDIS_OID_REQUEST *O
}, },
.InterruptModeration = NdisInterruptModerationNotSupported .InterruptModeration = NdisInterruptModerationNotSupported
}; };
size = (UINT)sizeof(intp); return TunOidQueryWriteBuf(OidRequest, &intp, (UINT)sizeof(intp));
buf = &intp;
break;
} }
case OID_PNP_QUERY_POWER: case OID_PNP_QUERY_POWER:
size = 0; OidRequest->DATA.QUERY_INFORMATION.BytesNeeded =
break; OidRequest->DATA.QUERY_INFORMATION.BytesWritten = 0;
return NDIS_STATUS_SUCCESS;
}
default:
OidRequest->DATA.QUERY_INFORMATION.BytesWritten = 0; OidRequest->DATA.QUERY_INFORMATION.BytesWritten = 0;
return NDIS_STATUS_INVALID_OID; return NDIS_STATUS_INVALID_OID;
} }
if (size > OidRequest->DATA.QUERY_INFORMATION.InformationBufferLength) {
OidRequest->DATA.QUERY_INFORMATION.BytesNeeded = size;
OidRequest->DATA.QUERY_INFORMATION.BytesWritten = 0;
return NDIS_STATUS_INVALID_LENGTH;
}
NdisMoveMemory(OidRequest->DATA.QUERY_INFORMATION.InformationBuffer, buf, size);
OidRequest->DATA.QUERY_INFORMATION.BytesNeeded = OidRequest->DATA.QUERY_INFORMATION.BytesWritten = size;
return NDIS_STATUS_SUCCESS;
}
static MINIPORT_OID_REQUEST TunOidRequest; static MINIPORT_OID_REQUEST TunOidRequest;
_Use_decl_annotations_ _Use_decl_annotations_
static NDIS_STATUS TunOidRequest(NDIS_HANDLE MiniportAdapterContext, PNDIS_OID_REQUEST OidRequest) static NDIS_STATUS TunOidRequest(NDIS_HANDLE MiniportAdapterContext, PNDIS_OID_REQUEST OidRequest)