3

NDIS フィルター ドライバーを開発してFilterReceiveNetBufferListsいますが、特定の条件下 (Wireshark を開くか、その [インターフェイス リスト] ボタンをクリックするなど) では呼び出されない (ネットワークがブロックされている) ことがわかります。しかし、キャプチャを開始すると、FilterReceiveNetBufferLists正常になります (ネットワークが復元されます)。これは非常に奇妙です。

WinPcap ドライバー (NPF_IoControl の BIOCQUERYOID & BIOCSETOID スイッチ ブランチ) の OID 発信元NDIS_STATUS_FAILUREの関数に手動で戻ると、ドライバーがネットワークをブロックしないことがわかりました (また、winpcap は機能しません)。NdisFOidRequest

NdisFOidRequest呼び出しに何か問題がありますか?

OID 要求を発信する Packet.c の DeviceIO ルーチン:

case BIOCQUERYOID:
case BIOCSETOID:

    TRACE_MESSAGE(PACKET_DEBUG_LOUD, "BIOCSETOID - BIOCQUERYOID");

    //
    // gain ownership of the Ndis Handle
    //
    if (NPF_StartUsingBinding(Open) == FALSE)
    {
        //
        // MAC unbindind or unbound
        //
        SET_FAILURE_INVALID_REQUEST();
        break;
    }


    // Extract a request from the list of free ones
    RequestListEntry = ExInterlockedRemoveHeadList(&Open->RequestList, &Open->RequestSpinLock);
    if (RequestListEntry == NULL)
    {
        //
        // Release ownership of the Ndis Handle
        //
        NPF_StopUsingBinding(Open);

        SET_FAILURE_NOMEM();
        break;
    }

    pRequest = CONTAINING_RECORD(RequestListEntry, INTERNAL_REQUEST, ListElement);

    //
    //  See if it is an Ndis request
    //
    OidData = Irp->AssociatedIrp.SystemBuffer;

    if ((IrpSp->Parameters.DeviceIoControl.InputBufferLength == IrpSp->Parameters.DeviceIoControl.OutputBufferLength) &&
        (IrpSp->Parameters.DeviceIoControl.InputBufferLength >= sizeof(PACKET_OID_DATA)) &&
        (IrpSp->Parameters.DeviceIoControl.InputBufferLength >= sizeof(PACKET_OID_DATA) - 1 + OidData->Length))
    {
        TRACE_MESSAGE2(PACKET_DEBUG_LOUD, "BIOCSETOID|BIOCQUERYOID Request: Oid=%08lx, Length=%08lx", OidData->Oid, OidData->Length);

        //
        //  The buffer is valid
        //
        NdisZeroMemory(&pRequest->Request, sizeof(NDIS_OID_REQUEST));
        pRequest->Request.Header.Type = NDIS_OBJECT_TYPE_OID_REQUEST;
        pRequest->Request.Header.Revision = NDIS_OID_REQUEST_REVISION_1;
        pRequest->Request.Header.Size = NDIS_SIZEOF_OID_REQUEST_REVISION_1;

        if (FunctionCode == BIOCSETOID)
        {
            pRequest->Request.RequestType = NdisRequestSetInformation;
            pRequest->Request.DATA.SET_INFORMATION.Oid = OidData->Oid;

            pRequest->Request.DATA.SET_INFORMATION.InformationBuffer = OidData->Data;
            pRequest->Request.DATA.SET_INFORMATION.InformationBufferLength = OidData->Length;
        }
        else
        {
            pRequest->Request.RequestType = NdisRequestQueryInformation;
            pRequest->Request.DATA.QUERY_INFORMATION.Oid = OidData->Oid;

            pRequest->Request.DATA.QUERY_INFORMATION.InformationBuffer = OidData->Data;
            pRequest->Request.DATA.QUERY_INFORMATION.InformationBufferLength = OidData->Length;
        }

        NdisResetEvent(&pRequest->InternalRequestCompletedEvent);

        if (*((PVOID *) pRequest->Request.SourceReserved) != NULL)
        {
            *((PVOID *) pRequest->Request.SourceReserved) = NULL;
        }
        //
        //  submit the request
        //
        pRequest->Request.RequestId = (PVOID) NPF6X_REQUEST_ID;
        ASSERT(Open->AdapterHandle != NULL);
        Status = NdisFOidRequest(Open->AdapterHandle, &pRequest->Request);
        //Status = NDIS_STATUS_FAILURE;
    }
    else
    {
        //
        // Release ownership of the Ndis Handle
        //
        NPF_StopUsingBinding(Open);

        //
        //  buffer too small
        //
        SET_FAILURE_BUFFER_SMALL();
        break;
    }

    if (Status == NDIS_STATUS_PENDING)
    {
        NdisWaitEvent(&pRequest->InternalRequestCompletedEvent, 1000);
        Status = pRequest->RequestStatus;
    }

    //
    // Release ownership of the Ndis Handle
    //
    NPF_StopUsingBinding(Open);

    //
    // Complete the request
    //
    if (FunctionCode == BIOCSETOID)
    {
        OidData->Length = pRequest->Request.DATA.SET_INFORMATION.BytesRead;
        TRACE_MESSAGE1(PACKET_DEBUG_LOUD, "BIOCSETOID completed, BytesRead = %u", OidData->Length);
    }
    else
    {
        if (FunctionCode == BIOCQUERYOID)
        {
            OidData->Length = pRequest->Request.DATA.QUERY_INFORMATION.BytesWritten;

            if (Status == NDIS_STATUS_SUCCESS)
            {
                //
                // check for the stupid bug of the Nortel driver ipsecw2k.sys v. 4.10.0.0 that doesn't set the BytesWritten correctly
                // The driver is the one shipped with Nortel client Contivity VPN Client V04_65.18, and the MD5 for the buggy (unsigned) driver
                // is 3c2ff8886976214959db7d7ffaefe724 *ipsecw2k.sys (there are multiple copies of this binary with the same exact version info!)
                // 
                // The (certified) driver shipped with Nortel client Contivity VPN Client V04_65.320 doesn't seem affected by the bug.
                //
                if (pRequest->Request.DATA.QUERY_INFORMATION.BytesWritten > pRequest->Request.DATA.QUERY_INFORMATION.InformationBufferLength)
                {
                    TRACE_MESSAGE2(PACKET_DEBUG_LOUD, "Bogus return from NdisRequest (query): Bytes Written (%u) > InfoBufferLength (%u)!!", pRequest->Request.DATA.QUERY_INFORMATION.BytesWritten, pRequest->Request.DATA.QUERY_INFORMATION.InformationBufferLength);

                    Status = NDIS_STATUS_INVALID_DATA;
                }
            }

            TRACE_MESSAGE1(PACKET_DEBUG_LOUD, "BIOCQUERYOID completed, BytesWritten = %u", OidData->Length);
        }
    }


    ExInterlockedInsertTailList(&Open->RequestList, &pRequest->ListElement, &Open->RequestSpinLock);

    if (Status == NDIS_STATUS_SUCCESS)
    {
        SET_RESULT_SUCCESS(sizeof(PACKET_OID_DATA) - 1 + OidData->Length);
    }
    else
    {
        SET_FAILURE_INVALID_REQUEST();
    }

    break;

3 つのフィルター OID ルーチン:

_Use_decl_annotations_
NDIS_STATUS
NPF_OidRequest(
    NDIS_HANDLE         FilterModuleContext,
    PNDIS_OID_REQUEST   Request
    )
{
    POPEN_INSTANCE          Open = (POPEN_INSTANCE) FilterModuleContext;
    NDIS_STATUS             Status;
    PNDIS_OID_REQUEST       ClonedRequest=NULL;
    BOOLEAN                 bSubmitted = FALSE;
    PFILTER_REQUEST_CONTEXT Context;
    BOOLEAN                 bFalse = FALSE;

    TRACE_ENTER();

    do
    {
        Status = NdisAllocateCloneOidRequest(Open->AdapterHandle,
                                            Request,
                                            NPF6X_ALLOC_TAG,
                                            &ClonedRequest);
        if (Status != NDIS_STATUS_SUCCESS)
        {
            TRACE_MESSAGE(PACKET_DEBUG_LOUD, "FilerOidRequest: Cannot Clone Request\n");
            break;
        }

        Context = (PFILTER_REQUEST_CONTEXT)(&ClonedRequest->SourceReserved[0]);
        *Context = Request;

        bSubmitted = TRUE;

        //
        // Use same request ID
        //
        ClonedRequest->RequestId = Request->RequestId;

        Open->PendingOidRequest = ClonedRequest;

        Status = NdisFOidRequest(Open->AdapterHandle, ClonedRequest);

        if (Status != NDIS_STATUS_PENDING)
        {
            NPF_OidRequestComplete(Open, ClonedRequest, Status);
            Status = NDIS_STATUS_PENDING;
        }


    }while (bFalse);

    if (bSubmitted == FALSE)
    {
        switch(Request->RequestType)
        {
            case NdisRequestMethod:
                Request->DATA.METHOD_INFORMATION.BytesRead = 0;
                Request->DATA.METHOD_INFORMATION.BytesNeeded = 0;
                Request->DATA.METHOD_INFORMATION.BytesWritten = 0;
                break;

            case NdisRequestSetInformation:
                Request->DATA.SET_INFORMATION.BytesRead = 0;
                Request->DATA.SET_INFORMATION.BytesNeeded = 0;
                break;

            case NdisRequestQueryInformation:
            case NdisRequestQueryStatistics:
            default:
                Request->DATA.QUERY_INFORMATION.BytesWritten = 0;
                Request->DATA.QUERY_INFORMATION.BytesNeeded = 0;
                break;
        }

    }

    TRACE_EXIT();
    return Status;

}

//-------------------------------------------------------------------

_Use_decl_annotations_
VOID
NPF_CancelOidRequest(
    NDIS_HANDLE             FilterModuleContext,
    PVOID                   RequestId
    )
{
    POPEN_INSTANCE                      Open = (POPEN_INSTANCE) FilterModuleContext;
    PNDIS_OID_REQUEST                   Request = NULL;
    PFILTER_REQUEST_CONTEXT             Context;
    PNDIS_OID_REQUEST                   OriginalRequest = NULL;
    BOOLEAN                             bFalse = FALSE;

    FILTER_ACQUIRE_LOCK(&Open->OIDLock, bFalse);

    Request = Open->PendingOidRequest;

    if (Request != NULL)
    {
        Context = (PFILTER_REQUEST_CONTEXT)(&Request->SourceReserved[0]);

        OriginalRequest = (*Context);
    }

    if ((OriginalRequest != NULL) && (OriginalRequest->RequestId == RequestId))
    {
        FILTER_RELEASE_LOCK(&Open->OIDLock, bFalse);

        NdisFCancelOidRequest(Open->AdapterHandle, RequestId);
    }
    else
    {
        FILTER_RELEASE_LOCK(&Open->OIDLock, bFalse);
    }
}

//-------------------------------------------------------------------

_Use_decl_annotations_
VOID
NPF_OidRequestComplete(
    NDIS_HANDLE         FilterModuleContext,
    PNDIS_OID_REQUEST   Request,
    NDIS_STATUS         Status
    )
{
    POPEN_INSTANCE                      Open = (POPEN_INSTANCE) FilterModuleContext;
    PNDIS_OID_REQUEST                   OriginalRequest;
    PFILTER_REQUEST_CONTEXT             Context;
    BOOLEAN                             bFalse = FALSE;

    TRACE_ENTER();

    Context = (PFILTER_REQUEST_CONTEXT)(&Request->SourceReserved[0]);
    OriginalRequest = (*Context);

    //
    // This is an internal request
    //
    if (OriginalRequest == NULL)
    {
        TRACE_MESSAGE1(PACKET_DEBUG_LOUD, "Status= %p", Status);
        NPF_InternalRequestComplete(Open, Request, Status);
        TRACE_EXIT();
        return;
    }


    FILTER_ACQUIRE_LOCK(&Open->OIDLock, bFalse);

    ASSERT(Open->PendingOidRequest == Request);
    Open->PendingOidRequest = NULL;

    FILTER_RELEASE_LOCK(&Open->OIDLock, bFalse);


    //
    // Copy the information from the returned request to the original request
    //
    switch(Request->RequestType)
    {
        case NdisRequestMethod:
            OriginalRequest->DATA.METHOD_INFORMATION.OutputBufferLength =  Request->DATA.METHOD_INFORMATION.OutputBufferLength;
            OriginalRequest->DATA.METHOD_INFORMATION.BytesRead = Request->DATA.METHOD_INFORMATION.BytesRead;
            OriginalRequest->DATA.METHOD_INFORMATION.BytesNeeded = Request->DATA.METHOD_INFORMATION.BytesNeeded;
            OriginalRequest->DATA.METHOD_INFORMATION.BytesWritten = Request->DATA.METHOD_INFORMATION.BytesWritten;
            break;

        case NdisRequestSetInformation:
            OriginalRequest->DATA.SET_INFORMATION.BytesRead = Request->DATA.SET_INFORMATION.BytesRead;
            OriginalRequest->DATA.SET_INFORMATION.BytesNeeded = Request->DATA.SET_INFORMATION.BytesNeeded;
            break;

        case NdisRequestQueryInformation:
        case NdisRequestQueryStatistics:
        default:
            OriginalRequest->DATA.QUERY_INFORMATION.BytesWritten = Request->DATA.QUERY_INFORMATION.BytesWritten;
            OriginalRequest->DATA.QUERY_INFORMATION.BytesNeeded = Request->DATA.QUERY_INFORMATION.BytesNeeded;
            break;
    }


    (*Context) = NULL;

    NdisFreeCloneOidRequest(Open->AdapterHandle, Request);

    NdisFOidRequestComplete(Open->AdapterHandle, OriginalRequest, Status);

    TRACE_EXIT();
}
4

1 に答える 1