aboutsummaryrefslogtreecommitdiffstats
path: root/wintun.c
diff options
context:
space:
mode:
authorSimon Rozman <simon@rozman.si>2019-04-05 11:04:13 +0200
committerSimon Rozman <simon@rozman.si>2019-04-05 12:57:22 +0200
commitbf48214c8c495738c3388129792358766544c2b4 (patch)
tree3cb4bd52635ab8e8472396cbd16c813b2c89c1d8 /wintun.c
parentAccess PowerState interlocked (diff)
downloadwintun-bf48214c8c495738c3388129792358766544c2b4.tar.xz
wintun-bf48214c8c495738c3388129792358766544c2b4.zip
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>
Diffstat (limited to 'wintun.c')
-rw-r--r--wintun.c110
1 files changed, 69 insertions, 41 deletions
diff --git a/wintun.c b/wintun.c
index beda27e..7fb49a5 100644
--- a/wintun.c
+++ b/wintun.c
@@ -1214,8 +1214,8 @@ static NDIS_STATUS TunOidSet(_Inout_ TUN_CTX *ctx, _Inout_ NDIS_OID_REQUEST *Oid
{
ASSERT(OidRequest->RequestType == NdisRequestSetInformation);
+ OidRequest->DATA.SET_INFORMATION.BytesNeeded =
OidRequest->DATA.SET_INFORMATION.BytesRead = 0;
- OidRequest->DATA.SET_INFORMATION.BytesNeeded = 0;
switch (OidRequest->DATA.SET_INFORMATION.Oid) {
case OID_GEN_CURRENT_PACKET_FILTER:
@@ -1249,57 +1249,98 @@ static NDIS_STATUS TunOidSet(_Inout_ TUN_CTX *ctx, _Inout_ NDIS_OID_REQUEST *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)
+_Must_inspect_result_
static NDIS_STATUS TunOidQuery(_Inout_ TUN_CTX *ctx, _Inout_ NDIS_OID_REQUEST *OidRequest)
{
ASSERT(OidRequest->RequestType == NdisRequestQueryInformation || OidRequest->RequestType == NdisRequestQueryStatistics);
- UINT value32;
- UINT size = sizeof(value32);
- const void *buf = &value32;
-
switch (OidRequest->DATA.QUERY_INFORMATION.Oid) {
case OID_GEN_MAXIMUM_TOTAL_SIZE:
case OID_GEN_TRANSMIT_BLOCK_SIZE:
case OID_GEN_RECEIVE_BLOCK_SIZE:
- value32 = TUN_EXCH_MAX_IP_PACKET_SIZE;
- break;
+ return TunOidQueryWrite(OidRequest, TUN_EXCH_MAX_IP_PACKET_SIZE);
case OID_GEN_TRANSMIT_BUFFER_SPACE:
case OID_GEN_RECEIVE_BUFFER_SPACE:
- value32 = TUN_EXCH_MAX_IP_PACKET_SIZE * TUN_EXCH_MAX_PACKETS;
- break;
+ return TunOidQueryWrite(OidRequest, TUN_EXCH_MAX_IP_PACKET_SIZE * TUN_EXCH_MAX_PACKETS);
case OID_GEN_VENDOR_ID:
- value32 = TunHtonl(TUN_VENDOR_ID);
- break;
+ return TunOidQueryWrite(OidRequest, TunHtonl(TUN_VENDOR_ID));
case OID_GEN_VENDOR_DESCRIPTION:
- size = (UINT)sizeof(TUN_VENDOR_NAME);
- buf = TUN_VENDOR_NAME;
- break;
+ return TunOidQueryWriteBuf(OidRequest, TUN_VENDOR_NAME, (UINT)sizeof(TUN_VENDOR_NAME));
case OID_GEN_VENDOR_DRIVER_VERSION:
- value32 = (WINTUN_VERSION_MAJ << 16) | WINTUN_VERSION_MIN;
- break;
+ return TunOidQueryWrite(OidRequest, (WINTUN_VERSION_MAJ << 16) | WINTUN_VERSION_MIN);
case OID_GEN_XMIT_OK:
- value32 = (UINT)(
+ return TunOidQueryWrite32or64(OidRequest,
InterlockedGet64((LONG64 *)&ctx->Statistics.ifHCOutUcastPkts ) +
InterlockedGet64((LONG64 *)&ctx->Statistics.ifHCOutMulticastPkts) +
InterlockedGet64((LONG64 *)&ctx->Statistics.ifHCOutBroadcastPkts));
- break;
case OID_GEN_RCV_OK:
- value32 = (UINT)(
+ return TunOidQueryWrite32or64(OidRequest,
InterlockedGet64((LONG64 *)&ctx->Statistics.ifHCInUcastPkts ) +
InterlockedGet64((LONG64 *)&ctx->Statistics.ifHCInMulticastPkts) +
InterlockedGet64((LONG64 *)&ctx->Statistics.ifHCInBroadcastPkts));
- break;
case OID_GEN_STATISTICS:
- size = (UINT)sizeof(ctx->Statistics);
- buf = &ctx->Statistics;
- break;
+ return TunOidQueryWriteBuf(OidRequest, &ctx->Statistics, (UINT)sizeof(ctx->Statistics));
case OID_GEN_INTERRUPT_MODERATION: {
static const NDIS_INTERRUPT_MODERATION_PARAMETERS intp = {
@@ -1310,30 +1351,17 @@ static NDIS_STATUS TunOidQuery(_Inout_ TUN_CTX *ctx, _Inout_ NDIS_OID_REQUEST *O
},
.InterruptModeration = NdisInterruptModerationNotSupported
};
- size = (UINT)sizeof(intp);
- buf = &intp;
- break;
+ return TunOidQueryWriteBuf(OidRequest, &intp, (UINT)sizeof(intp));
}
case OID_PNP_QUERY_POWER:
- size = 0;
- break;
-
- default:
- OidRequest->DATA.QUERY_INFORMATION.BytesWritten = 0;
- return NDIS_STATUS_INVALID_OID;
- }
-
- if (size > OidRequest->DATA.QUERY_INFORMATION.InformationBufferLength) {
- OidRequest->DATA.QUERY_INFORMATION.BytesNeeded = size;
+ OidRequest->DATA.QUERY_INFORMATION.BytesNeeded =
OidRequest->DATA.QUERY_INFORMATION.BytesWritten = 0;
- return NDIS_STATUS_INVALID_LENGTH;
+ return NDIS_STATUS_SUCCESS;
}
- NdisMoveMemory(OidRequest->DATA.QUERY_INFORMATION.InformationBuffer, buf, size);
- OidRequest->DATA.QUERY_INFORMATION.BytesNeeded = OidRequest->DATA.QUERY_INFORMATION.BytesWritten = size;
-
- return NDIS_STATUS_SUCCESS;
+ OidRequest->DATA.QUERY_INFORMATION.BytesWritten = 0;
+ return NDIS_STATUS_INVALID_OID;
}
static MINIPORT_OID_REQUEST TunOidRequest;