コード例 #1
0
ファイル: filter.c プロジェクト: HarryMorris/openthread
_Use_decl_annotations_
NDIS_STATUS
FilterPause(
    NDIS_HANDLE                     FilterModuleContext,
    PNDIS_FILTER_PAUSE_PARAMETERS   PauseParameters
    )
/*++

Routine Description:

    Filter pause routine.
    Complete all the outstanding sends and queued sends,
    wait for all the outstanding recvs to be returned
    and return all the queued receives.

Arguments:

    FilterModuleContext - pointer to the filter context stucture
    PauseParameters     - additional information about the pause

Return Value:

    NDIS_STATUS_SUCCESS if filter pauses successfully, NDIS_STATUS_PENDING
    if not.  No other return value is allowed (pause must succeed, eventually).

N.B.: When the filter is in Pausing state, it can still process OID requests, 
    complete sending, and returning packets to NDIS, and also indicate status.
    After this function completes, the filter must not attempt to send or 
    receive packets, but it may still process OID requests and status 
    indications.

--*/
{
    PMS_FILTER      pFilter = (PMS_FILTER)(FilterModuleContext);
    NDIS_STATUS     Status = STATUS_SUCCESS;

    UNREFERENCED_PARAMETER(PauseParameters);

    LogFuncEntryMsg(DRIVER_DEFAULT, "Filter: %p", FilterModuleContext);

    //
    // Set the flag that the filter is going to pause
    //
    NT_ASSERT(pFilter->State == FilterRunning);
    NdisAcquireSpinLock(&FilterListLock);
    pFilter->State = FilterPausing;
    NdisReleaseSpinLock(&FilterListLock);

    //
    // Send final notification of interface removal
    //
    otLwfNotifyDeviceAvailabilityChange(pFilter, FALSE);
    LogInfo(DRIVER_DEFAULT, "Interface %!GUID! removal.", &pFilter->InterfaceGuid);

    //
    // Disable external references and wait for existing calls to complete
    //
    LogInfo(DRIVER_DEFAULT, "Disabling and waiting for external references to release");
    ExWaitForRundownProtectionRelease(&pFilter->ExternalRefs);
    LogInfo(DRIVER_DEFAULT, "External references released.");

    //
    // Clean up based on the device mode
    //
    if (pFilter->DeviceStatus == OTLWF_DEVICE_STATUS_RADIO_MODE)
    {
        otLwfUninitializeThreadMode(pFilter);
    }
    else if (pFilter->DeviceStatus == OTLWF_DEVICE_STATUS_THREAD_MODE)
    {
        otLwfTunUninitialize(pFilter);
    }

    pFilter->DeviceStatus = OTLWF_DEVICE_STATUS_UNINTIALIZED;

    //
    // Clean up the Spinel command processing
    //
    otLwfCmdUninitialize(pFilter);

    //
    // Set the state back to Paused now that we are done
    //
    pFilter->State = FilterPaused;

    LogFuncExitNDIS(DRIVER_DEFAULT, Status);
    return Status;
}
コード例 #2
0
ファイル: tunnel.c プロジェクト: GiedriusM/openthread
NDIS_STATUS 
otLwfTunInitialize(
    _In_ PMS_FILTER pFilter
    )
{
    NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
    HANDLE threadHandle = NULL;

    LogFuncEntry(DRIVER_DEFAULT);

    NT_ASSERT(pFilter->DeviceCapabilities & OTLWF_DEVICE_CAP_THREAD_1_0);
    
    KeInitializeEvent(
        &pFilter->TunWorkerThreadStopEvent,
        SynchronizationEvent, // auto-clearing event
        FALSE                 // event initially non-signalled
        );
    KeInitializeEvent(
        &pFilter->TunWorkerThreadAddressChangedEvent,
        SynchronizationEvent, // auto-clearing event
        FALSE                 // event initially non-signalled
        );

    // Start the worker thread
    Status = PsCreateSystemThread(
                &threadHandle,                  // ThreadHandle
                THREAD_ALL_ACCESS,              // DesiredAccess
                NULL,                           // ObjectAttributes
                NULL,                           // ProcessHandle
                NULL,                           // ClientId
                otLwfTunWorkerThread,           // StartRoutine
                pFilter                         // StartContext
                );
    if (!NT_SUCCESS(Status))
    {
        LogError(DRIVER_DEFAULT, "PsCreateSystemThread failed, %!STATUS!", Status);
        goto error;
    }

    // Grab the object reference to the worker thread
    Status = ObReferenceObjectByHandle(
                threadHandle,
                THREAD_ALL_ACCESS,
                *PsThreadType,
                KernelMode,
                &pFilter->TunWorkerThread,
                NULL
                );
    if (!NT_VERIFYMSG("ObReferenceObjectByHandle can't fail with a valid kernel handle", NT_SUCCESS(Status)))
    {
        LogError(DRIVER_DEFAULT, "ObReferenceObjectByHandle failed, %!STATUS!", Status);
        KeSetEvent(&pFilter->TunWorkerThreadStopEvent, IO_NO_INCREMENT, FALSE);
    }

    // Make sure to enable RLOC passthrough
    Status =
        otLwfCmdSetProp(
            pFilter,
            SPINEL_PROP_THREAD_RLOC16_DEBUG_PASSTHRU,
            SPINEL_DATATYPE_BOOL_S,
            TRUE
        );
    if (!NT_SUCCESS(Status))
    {
        LogError(DRIVER_DEFAULT, "Enabling RLOC pass through failed, %!STATUS!", Status);
        goto error;
    }

    // TODO - Query other values and capabilities

error:

    if (!NT_SUCCESS(Status))
    {
        otLwfTunUninitialize(pFilter);
    }

    LogFuncExitNDIS(DRIVER_DEFAULT, Status);

    return Status;
}
コード例 #3
0
ファイル: filter.c プロジェクト: HarryMorris/openthread
_Use_decl_annotations_
NDIS_STATUS
FilterRestart(
    NDIS_HANDLE                     FilterModuleContext,
    PNDIS_FILTER_RESTART_PARAMETERS RestartParameters
    )
/*++

Routine Description:

    Filter restart routine.
    Start the datapath - begin sending and receiving NBLs.

Arguments:

    FilterModuleContext - pointer to the filter context stucture.
    RestartParameters   - additional information about the restart operation.

Return Value:

    NDIS_STATUS_SUCCESS: if filter restarts successfully
    NDIS_STATUS_XXX: Otherwise.

--*/
{
    NTSTATUS            NtStatus = STATUS_SUCCESS;
    NDIS_STATUS         NdisStatus = NDIS_STATUS_SUCCESS;
    PMS_FILTER          pFilter = (PMS_FILTER)FilterModuleContext;
    PVOID               SpinelCapsDataBuffer = NULL;
    const uint8_t*      SpinelCapsPtr = NULL;
    spinel_size_t       SpinelCapsLen = 0;
    NL_INTERFACE_KEY    key = {0};
    NL_INTERFACE_RW     interfaceRw;
    ULONG               ThreadOnHost = TRUE;

    PNDIS_RESTART_GENERAL_ATTRIBUTES NdisGeneralAttributes;
    PNDIS_RESTART_ATTRIBUTES         NdisRestartAttributes;

    LogFuncEntryMsg(DRIVER_DEFAULT, "Filter: %p", FilterModuleContext);

    NT_ASSERT(pFilter->State == FilterPaused);

    NdisRestartAttributes = RestartParameters->RestartAttributes;

    //
    // If NdisRestartAttributes is not NULL, then the filter can modify generic 
    // attributes and add new media specific info attributes at the end. 
    // Otherwise, if NdisRestartAttributes is NULL, the filter should not try to 
    // modify/add attributes.
    //
    if (NdisRestartAttributes != NULL)
    {
        ASSERT(NdisRestartAttributes->Oid == OID_GEN_MINIPORT_RESTART_ATTRIBUTES);

        NdisGeneralAttributes = (PNDIS_RESTART_GENERAL_ATTRIBUTES)NdisRestartAttributes->Data;

        //
        // Check to see if we need to change any attributes. For example, the
        // driver can change the current MAC address here. Or the driver can add
        // media specific info attributes.
        //
        NdisGeneralAttributes->LookaheadSize = 128;
    }

    // Initialize the Spinel command processing
    NdisStatus = otLwfCmdInitialize(pFilter);
    if (NdisStatus != NDIS_STATUS_SUCCESS)
    {
        LogError(DRIVER_DEFAULT, "otLwfCmdInitialize failed, %!NDIS_STATUS!", NdisStatus);
        goto exit;
    }

    // Query the device capabilities
    NtStatus = otLwfCmdGetProp(pFilter, SpinelCapsDataBuffer, SPINEL_PROP_CAPS, SPINEL_DATATYPE_DATA_S, &SpinelCapsPtr, &SpinelCapsLen);
    if (!NT_SUCCESS(NtStatus))
    {
        NdisStatus = NDIS_STATUS_NOT_SUPPORTED;
        LogError(DRIVER_DEFAULT, "Failed to query SPINEL_PROP_CAPS, %!STATUS!", NtStatus);
        goto exit;
    }

    // Iterate and process returned capabilities
    while (SpinelCapsLen > 0)
    {
        ULONG SpinelCap = 0;
        spinel_ssize_t len = spinel_datatype_unpack(SpinelCapsPtr, SpinelCapsLen, SPINEL_DATATYPE_UINT_PACKED_S, &SpinelCap);
        if (len < 1) break;
        SpinelCapsLen -= (spinel_size_t)len;

        switch (SpinelCap)
        {
        case SPINEL_CAP_MAC_RAW:
            pFilter->DeviceCapabilities |= OTLWF_DEVICE_CAP_RADIO;
            pFilter->DeviceCapabilities |= OTLWF_DEVICE_CAP_RADIO_ACK_TIMEOUT;
            pFilter->DeviceCapabilities |= OTLWF_DEVICE_CAP_RADIO_ENERGY_SCAN;
            break;
        case SPINEL_CAP_NET_THREAD_1_0:
            pFilter->DeviceCapabilities |= OTLWF_DEVICE_CAP_THREAD_1_0;
            break;
        default:
            break;
        }
    }

    // Set the state indicating where we should be running the Thread logic (Host or Device).
    if (!NT_SUCCESS(GetRegDWORDValue(pFilter, L"RunOnHost", &ThreadOnHost)))
    {
        // Default to running on the host if the key isn't present
        ThreadOnHost = TRUE;
        SetRegDWORDValue(pFilter, L"RunOnHost", ThreadOnHost);
    }

    LogInfo(DRIVER_DEFAULT, "Filter: %p initializing ThreadOnHost=%d", FilterModuleContext, ThreadOnHost);

    // Initialize the processing logic
    if (ThreadOnHost)
    {
        // Ensure the device has the capabilities to support raw radio commands
        if ((pFilter->DeviceCapabilities & OTLWF_DEVICE_CAP_RADIO) == 0)
        {
            LogError(DRIVER_DEFAULT, "Failed to start because device doesn't support raw radio commands");
            NdisStatus = NDIS_STATUS_NOT_SUPPORTED;
            goto exit;
        }

        pFilter->DeviceStatus = OTLWF_DEVICE_STATUS_RADIO_MODE;
        NtStatus = otLwfInitializeThreadMode(pFilter);
        if (!NT_SUCCESS(NtStatus))
        {
            LogError(DRIVER_DEFAULT, "otLwfInitializeThreadMode failed, %!STATUS!", NtStatus);
            NdisStatus = NDIS_STATUS_FAILURE;
            pFilter->DeviceStatus = OTLWF_DEVICE_STATUS_UNINTIALIZED;
            goto exit;
        }
    }
    else
    {
        // Ensure the device has the capabilities to support Thread commands
        if ((pFilter->DeviceCapabilities & OTLWF_DEVICE_CAP_THREAD_1_0) == 0)
        {
            LogError(DRIVER_DEFAULT, "Failed to start because device doesn't support thread commands");
            NdisStatus = NDIS_STATUS_NOT_SUPPORTED;
            goto exit;
        }

        pFilter->DeviceStatus = OTLWF_DEVICE_STATUS_THREAD_MODE;
        NtStatus = otLwfTunInitialize(pFilter);
        if (!NT_SUCCESS(NtStatus))
        {
            LogError(DRIVER_DEFAULT, "otLwfInitializeTunnelMode failed, %!STATUS!", NtStatus);
            NdisStatus = NDIS_STATUS_FAILURE;
            pFilter->DeviceStatus = OTLWF_DEVICE_STATUS_UNINTIALIZED;
            goto exit;
        }
    }

    //
    // Disable DAD and Neighbor advertisements
    //
    key.Luid = pFilter->InterfaceLuid;
    NlInitializeInterfaceRw(&interfaceRw);
    interfaceRw.DadTransmits = 0;
    interfaceRw.SendUnsolicitedNeighborAdvertisementOnDad = FALSE;
  
    NtStatus =
        NsiSetAllParameters(
            NsiActive,
            NsiSetDefault,
            &NPI_MS_IPV6_MODULEID,
            NlInterfaceObject,
            &key,
            sizeof(key),
            &interfaceRw,
            sizeof(interfaceRw));
    if (!NT_SUCCESS(NtStatus))
    {
        LogError(DRIVER_DEFAULT, "NsiSetAllParameters (NlInterfaceObject) failed, %!STATUS!", NtStatus);
        NdisStatus = NDIS_STATUS_FAILURE;
        goto exit;
    }

    //
    // Enable the external references to the filter
    //
    ExReInitializeRundownProtection(&pFilter->ExternalRefs);

    //
    // If everything is OK, set the filter in running state.
    //
    pFilter->State = FilterRunning; // when successful
    otLwfNotifyDeviceAvailabilityChange(pFilter, TRUE);
    LogInfo(DRIVER_DEFAULT, "Interface %!GUID! arrival, Filter=%p", &pFilter->InterfaceGuid, pFilter);

exit:

    //
    // Ensure the state is Paused if restart failed.
    //
    if (NdisStatus != NDIS_STATUS_SUCCESS)
    {
        pFilter->State = FilterPaused;

        if (pFilter->DeviceStatus == OTLWF_DEVICE_STATUS_RADIO_MODE)
        {
            otLwfUninitializeThreadMode(pFilter);
        }
        else if (pFilter->DeviceStatus == OTLWF_DEVICE_STATUS_THREAD_MODE)
        {
            otLwfTunUninitialize(pFilter);
        }

        pFilter->DeviceStatus = OTLWF_DEVICE_STATUS_UNINTIALIZED;

        // Clean up Spinel command processing
        otLwfCmdUninitialize(pFilter);
    }

    // Free the buffer for the capabilities we queried
    if (SpinelCapsDataBuffer != NULL)
    {
        FILTER_FREE_MEM(SpinelCapsDataBuffer);
    }

    LogFuncExitNDIS(DRIVER_DEFAULT, NdisStatus);
    return NdisStatus;
}