Exemplo n.º 1
0
VOID
otLwfEventProcessingIndicateNewNetBufferLists(
    _In_ PMS_FILTER             pFilter,
    _In_ BOOLEAN                DispatchLevel,
    _In_ PNET_BUFFER_LIST       NetBufferLists
    )
{
    POTLWF_NBL_EVENT Event = FILTER_ALLOC_MEM(pFilter->FilterHandle, sizeof(OTLWF_NBL_EVENT));
    if (Event == NULL)
    {
        LogWarning(DRIVER_DATA_PATH, "Failed to alloc new OTLWF_NBL_EVENT");
        otLwfCompleteNBLs(pFilter, DispatchLevel, NetBufferLists, STATUS_INSUFFICIENT_RESOURCES);
        return;
    }

    Event->NetBufferLists = NetBufferLists;

    // Add the event to the queue
    FILTER_ACQUIRE_LOCK(&pFilter->EventsLock, DispatchLevel);
    InsertTailList(&pFilter->NBLsHead, &Event->Link);
    FILTER_RELEASE_LOCK(&pFilter->EventsLock, DispatchLevel);
    
    // Set the event to indicate we have a new NBL to process
    KeSetEvent(&pFilter->EventWorkerThreadProcessNBLs, 0, FALSE);
}
Exemplo n.º 2
0
VOID
otLwfEventProcessingIndicateAddressChange(
    _In_ PMS_FILTER             pFilter,
    _In_ MIB_NOTIFICATION_TYPE  NotificationType,
    _In_ PIN6_ADDR              pAddr
    )
{
    LogFuncEntryMsg(DRIVER_DEFAULT, "Filter: %p", pFilter);

    NT_ASSERT(pFilter->DeviceStatus == OTLWF_DEVICE_STATUS_RADIO_MODE);

    POTLWF_ADDR_EVENT Event = FILTER_ALLOC_MEM(pFilter->FilterHandle, sizeof(OTLWF_ADDR_EVENT));
    if (Event == NULL)
    {
        LogWarning(DRIVER_DEFAULT, "Failed to alloc new OTLWF_ADDR_EVENT");
    }
    else
    {
        Event->NotificationType = NotificationType;
        Event->Address = *pAddr;

        // Add the event to the queue
        NdisAcquireSpinLock(&pFilter->EventsLock);
        InsertTailList(&pFilter->AddressChangesHead, &Event->Link);
        NdisReleaseSpinLock(&pFilter->EventsLock);

        // Set the event to indicate we have a new address to process
        KeSetEvent(&pFilter->EventWorkerThreadProcessAddressChanges, 0, FALSE);
    }

    LogFuncExit(DRIVER_DEFAULT);
}
Exemplo n.º 3
0
NTSTATUS FilterDeleteSetting(_In_ PMS_FILTER pFilter, uint16_t aKey, int aIndex)
{
    HANDLE regKey = NULL;
    OBJECT_ATTRIBUTES attributes;
    DECLARE_UNICODE_STRING_SIZE(Name, 20);

    // Convert 'aKey' to a string
    RtlIntegerToUnicodeString((ULONG)aKey, 16, &Name);

    InitializeObjectAttributes(
        &attributes,
        &Name,
        OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
        pFilter->otSettingsRegKey,
        NULL);

    // Open the registry key
    NTSTATUS status =
        ZwOpenKey(
            &regKey,
            KEY_ALL_ACCESS,
            &attributes);

    if (!NT_SUCCESS(status))
    {
        // Key doesn't exist
        goto error;
    }

    // If 'aIndex' is -1 then delete the whole key, otherwise delete the individual value
    if (aIndex == -1)
    {
        // Delete the registry key
        status = ZwDeleteKey(regKey);
    }
    else
    {
        UCHAR KeyInfoBuffer[128] = { 0 };
        PKEY_FULL_INFORMATION pKeyInfo = (PKEY_FULL_INFORMATION)KeyInfoBuffer;
        ULONG KeyInfoLength = sizeof(KeyInfoBuffer);

        // When deleting an individual value, since order doesn't matter, we will actually
        // copy the last value over the one being deleted and then delete the last value; so
        // we maintain a contiguous list of numbered values

        // Query the number of values
        // Note: Can't use helper function because we already have the key open
        status =
            ZwQueryKey(
                regKey,
                KeyValueFullInformation,
                pKeyInfo,
                KeyInfoLength,
                &KeyInfoLength);

        if (!NT_SUCCESS(status))
        {
            LogError(DRIVER_DEFAULT, "ZwQueryKey for %S value failed, %!STATUS!", Name.Buffer, status);
            goto error;
        }

        if ((ULONG)aIndex >= pKeyInfo->Values)
        {
            // Attempt to delete beyond the end of the list
            status = STATUS_OBJECT_NAME_NOT_FOUND;
            goto error;
        }
        else if (pKeyInfo->Values == 1)
        {
            // Deleting the only value on the key, go ahead and delete the entire key
            status = ZwDeleteKey(regKey);
        }
        else if (pKeyInfo->Values - 1 != (ULONG)aIndex)
        {
            // We aren't deleting the last value so we need to copy the last value
            // over this one, and then delete the last one.

            PKEY_VALUE_PARTIAL_INFORMATION pValueInfo = NULL;
            ULONG ValueInfoLength = 0;

            // Convert pKeyInfo->Values-1 to a string
            RtlIntegerToUnicodeString(pKeyInfo->Values - 1, 16, &Name);

            // Query the key data buffer size
            status = ZwQueryValueKey(
                regKey,
                &Name,
                KeyValuePartialInformation,
                pValueInfo,
                0,
                &ValueInfoLength);

            NT_ASSERT(status != STATUS_SUCCESS);
            if (status != STATUS_BUFFER_TOO_SMALL)
            {
                LogVerbose(DRIVER_DEFAULT, "ZwQueryValueKey for %S value failed, %!STATUS!", Name.Buffer, status);
                goto error;
            }

            pValueInfo = FILTER_ALLOC_MEM(pFilter->FilterHandle, ValueInfoLength);
            if (pValueInfo == NULL)
            {
                status = STATUS_INSUFFICIENT_RESOURCES;
                goto error;
            }

            // Query the data buffer
            status = ZwQueryValueKey(
                regKey,
                &Name,
                KeyValuePartialInformation,
                pValueInfo,
                ValueInfoLength,
                &ValueInfoLength);

            if (!NT_SUCCESS(status))
            {
                LogError(DRIVER_DEFAULT, "ZwQueryValueKey for %S value failed, %!STATUS!", Name.Buffer, status);
                goto cleanup;
            }

            // Delete the registry value
            status =
                ZwDeleteValueKey(
                    regKey,
                    &Name);

            if (!NT_SUCCESS(status))
            {
                LogError(DRIVER_DEFAULT, "ZwDeleteValueKey for %S value failed, %!STATUS!", Name.Buffer, status);
                goto cleanup;
            }

            // Convert 'aIndex' to a string
            RtlIntegerToUnicodeString((ULONG)aIndex, 16, &Name);

            // Write the data to the registry key we are deleting
            status =
                ZwSetValueKey(
                    regKey,
                    &Name,
                    0,
                    REG_BINARY,
                    (PVOID)pValueInfo->Data,
                    pValueInfo->DataLength);

            if (!NT_SUCCESS(status))
            {
                LogError(DRIVER_DEFAULT, "ZwSetValueKey for %S value failed, %!STATUS!", Name.Buffer, status);
                goto cleanup;
            }

        cleanup:

            if (pValueInfo) FILTER_FREE_MEM(pValueInfo);
        }
        else
        {
            // Deleting the last value in the list (but not the only value)
            // Just delete the value directly. No need to copy any others.

            // Convert 'aIndex' to a string
            RtlIntegerToUnicodeString((ULONG)aIndex, 16, &Name);

            // Delete the registry value
            status =
                ZwDeleteValueKey(
                    regKey,
                    &Name);
        }
    }

error:

    if (regKey) ZwClose(regKey);

    return status;
}
Exemplo n.º 4
0
NTSTATUS FilterReadSetting(_In_ PMS_FILTER pFilter, uint16_t aKey, int aIndex, uint8_t *aValue, uint16_t *aValueLength)
{
    HANDLE regKey = NULL;
    OBJECT_ATTRIBUTES attributes;
    DECLARE_UNICODE_STRING_SIZE(Name, 20);
    PKEY_VALUE_PARTIAL_INFORMATION pInfo = NULL;
    ULONG InfoLength = sizeof(*pInfo) + *aValueLength;

    // Convert 'aKey' to a string
    RtlIntegerToUnicodeString((ULONG)aKey, 16, &Name);

    InitializeObjectAttributes(
        &attributes,
        &Name,
        OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
        pFilter->otSettingsRegKey,
        NULL);

    // Open the registry key
    NTSTATUS status =
        ZwOpenKey(
            &regKey,
            KEY_ALL_ACCESS,
            &attributes);

    if (!NT_SUCCESS(status))
    {
        // Key doesn't exist
        goto error;
    }

    // Convert 'aIndex' to a string
    RtlIntegerToUnicodeString((ULONG)aIndex, 16, &Name);

    // Allocate buffer for query
    pInfo = FILTER_ALLOC_MEM(pFilter->FilterHandle, InfoLength);
    if (pInfo == NULL)
    {
        status = STATUS_INSUFFICIENT_RESOURCES;
        goto error;
    }

    // Query the data
    status = ZwQueryValueKey(
        regKey,
        &Name,
        KeyValuePartialInformation,
        pInfo,
        InfoLength,
        &InfoLength);

    if (!NT_SUCCESS(status))
    {
        LogVerbose(DRIVER_DEFAULT, "ZwQueryValueKey for %S value failed, %!STATUS!", Name.Buffer, status);
        goto error;
    }

    NT_ASSERT(*aValueLength >= pInfo->DataLength);
    *aValueLength = (uint16_t)pInfo->DataLength;
    if (aValue)
    {
        memcpy(aValue, pInfo->Data, pInfo->DataLength);
    }

error:

    if (pInfo) FILTER_FREE_MEM(pInfo);
    if (regKey) ZwClose(regKey);

    return status;
}
Exemplo n.º 5
0
    
    // Set the event to indicate we have a new NBL to process
    KeSetEvent(&pFilter->EventWorkerThreadProcessNBLs, 0, FALSE);
}

_IRQL_requires_max_(DISPATCH_LEVEL)
VOID
otLwfEventProcessingIndicateNewMacFrameCommand(
    _In_ PMS_FILTER             pFilter,
    _In_ BOOLEAN                DispatchLevel,
    _In_reads_bytes_(BufferLength) 
         const uint8_t*         Buffer,
    _In_ uint8_t                BufferLength
    )
{
    POTLWF_MAC_FRAME_EVENT Event = FILTER_ALLOC_MEM(pFilter->FilterHandle, FIELD_OFFSET(OTLWF_MAC_FRAME_EVENT, Buffer) + BufferLength);
    if (Event == NULL)
    {
        LogWarning(DRIVER_DATA_PATH, "Failed to alloc new OTLWF_MAC_FRAME_EVENT");
        return;
    }

    Event->BufferLength = BufferLength;
    memcpy(Event->Buffer, Buffer, BufferLength);

    // Add the event to the queue
    FILTER_ACQUIRE_LOCK(&pFilter->EventsLock, DispatchLevel);
    InsertTailList(&pFilter->MacFramesHead, &Event->Link);
    FILTER_RELEASE_LOCK(&pFilter->EventsLock, DispatchLevel);
    
    // Set the event to indicate we have a new Mac Frame to process
Exemplo n.º 6
0
_Use_decl_annotations_
NDIS_STATUS
FilterAttach(
    NDIS_HANDLE                     NdisFilterHandle,
    NDIS_HANDLE                     FilterDriverContext,
    PNDIS_FILTER_ATTACH_PARAMETERS  AttachParameters
    )
/*++

Routine Description:

    Filter attach routine.
    Create filter's context, allocate NetBufferLists and NetBuffer pools and any
    other resources, and read configuration if needed.

Arguments:

    NdisFilterHandle - Specify a handle identifying this instance of the filter. FilterAttach
                       should save this handle. It is a required  parameter in subsequent calls
                       to NdisFxxx functions.
    FilterDriverContext - Filter driver context passed to NdisFRegisterFilterDriver.

    AttachParameters - attach parameters

Return Value:

    NDIS_STATUS_SUCCESS: FilterAttach successfully allocated and initialize data structures
                         for this filter instance.
    NDIS_STATUS_RESOURCES: FilterAttach failed due to insufficient resources.
    NDIS_STATUS_FAILURE: FilterAttach could not set up this instance of this filter and it has called
                         NdisWriteErrorLogEntry with parameters specifying the reason for failure.

N.B.:  FILTER can use NdisRegisterDeviceEx to create a device, so the upper 
    layer can send Irps to the filter.

--*/
{
    PMS_FILTER              pFilter = NULL;
    NDIS_STATUS             Status = NDIS_STATUS_SUCCESS;
    NTSTATUS                NtStatus;
    NDIS_FILTER_ATTRIBUTES  FilterAttributes;
    ULONG                   Size;
    COMPARTMENT_ID          OriginalCompartmentID;
    OBJECT_ATTRIBUTES       ObjectAttributes = {0};

    const ULONG RegKeyOffset = ARRAYSIZE(L"\\REGISTRY\\MACHINE\\SYSTEM\\CurrentControlSet\\Services\\otlwf\\Parameters\\NdisAdapters\\") - 1;
    DECLARE_CONST_UNICODE_STRING(RegKeyPath, L"\\REGISTRY\\MACHINE\\SYSTEM\\CurrentControlSet\\Services\\otlwf\\Parameters\\NdisAdapters\\{00000000-0000-0000-0000-000000000000}");
    RtlCopyMemory(RegKeyPath.Buffer + RegKeyOffset, AttachParameters->BaseMiniportName->Buffer + 8, sizeof(L"{00000000-0000-0000-0000-000000000000}"));

    LogFuncEntry(DRIVER_DEFAULT);

    do
    {
        ASSERT(FilterDriverContext == (NDIS_HANDLE)FilterDriverObject);
        if (FilterDriverContext != (NDIS_HANDLE)FilterDriverObject)
        {
            Status = NDIS_STATUS_INVALID_PARAMETER;
            break;
        }

        // Verify the media type is supported.  This is a last resort; the
        // the filter should never have been bound to an unsupported miniport
        // to begin with.
        if (AttachParameters->MiniportMediaType != NdisMediumIP)
        {
            LogError(DRIVER_DEFAULT, "Unsupported media type, 0x%x.", (ULONG)AttachParameters->MiniportMediaType);
            Status = NDIS_STATUS_INVALID_PARAMETER;
            break;
        }

        Size = sizeof(MS_FILTER) +  AttachParameters->BaseMiniportInstanceName->Length;

        pFilter = (PMS_FILTER)FILTER_ALLOC_MEM(NdisFilterHandle, Size);
        if (pFilter == NULL)
        {
            LogWarning(DRIVER_DEFAULT, "Failed to allocate context structure, 0x%x bytes", Size);
            Status = NDIS_STATUS_RESOURCES;
            break;
        }

        NdisZeroMemory(pFilter, sizeof(MS_FILTER));

        LogVerbose(DRIVER_DEFAULT, "Opening interface registry key %S", RegKeyPath.Buffer);

        InitializeObjectAttributes(
            &ObjectAttributes,
            (PUNICODE_STRING)&RegKeyPath,
            OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
            NULL,
            NULL);

        // Open the registry key
        NtStatus = ZwOpenKey(&pFilter->InterfaceRegKey, KEY_ALL_ACCESS, &ObjectAttributes);
        if (!NT_SUCCESS(NtStatus))
        {
            LogError(DRIVER_DEFAULT, "ZwOpenKey failed to open %S, %!STATUS!", RegKeyPath.Buffer, NtStatus);
            Status = NDIS_STATUS_FAILURE;
            break;
        }

        // Format of "\DEVICE\{5BA90C49-0D7E-455B-8D3B-614F6714A212}"
        AttachParameters->BaseMiniportName->Buffer += 8;
        AttachParameters->BaseMiniportName->Length -= 8 * sizeof(WCHAR);
        NtStatus = RtlGUIDFromString(AttachParameters->BaseMiniportName, &pFilter->InterfaceGuid);
        AttachParameters->BaseMiniportName->Buffer -= 8;
        AttachParameters->BaseMiniportName->Length += 8 * sizeof(WCHAR);
        if (!NT_SUCCESS(NtStatus))
        {
            LogError(DRIVER_DEFAULT, "Failed to convert FilterModuleGuidName to a GUID, %!STATUS!", NtStatus);
            Status = NDIS_STATUS_FAILURE;
            break;
        }

        pFilter->InterfaceFriendlyName.Length = pFilter->InterfaceFriendlyName.MaximumLength = AttachParameters->BaseMiniportInstanceName->Length;
        pFilter->InterfaceFriendlyName.Buffer = (PWSTR)((PUCHAR)pFilter + sizeof(MS_FILTER));
        NdisMoveMemory(pFilter->InterfaceFriendlyName.Buffer,
                        AttachParameters->BaseMiniportInstanceName->Buffer,
                        pFilter->InterfaceFriendlyName.Length);

        pFilter->InterfaceIndex = AttachParameters->BaseMiniportIfIndex;
        pFilter->InterfaceLuid = AttachParameters->BaseMiniportNetLuid;
        pFilter->InterfaceCompartmentID = UNSPECIFIED_COMPARTMENT_ID;
        pFilter->FilterHandle = NdisFilterHandle;

        NdisZeroMemory(&FilterAttributes, sizeof(NDIS_FILTER_ATTRIBUTES));
        FilterAttributes.Header.Revision = NDIS_FILTER_ATTRIBUTES_REVISION_1;
        FilterAttributes.Header.Size = sizeof(NDIS_FILTER_ATTRIBUTES);
        FilterAttributes.Header.Type = NDIS_OBJECT_TYPE_FILTER_ATTRIBUTES;
        FilterAttributes.Flags = 0;

        NDIS_DECLARE_FILTER_MODULE_CONTEXT(MS_FILTER);
        Status = NdisFSetAttributes(NdisFilterHandle, pFilter, &FilterAttributes);
        if (Status != NDIS_STATUS_SUCCESS)
        {
            LogError(DRIVER_DEFAULT, "Failed to set attributes, %!NDIS_STATUS!", Status);
            break;
        }

        // Filter initially in Paused state
        pFilter->State = FilterPaused;

        // Initialize rundowns to disabled with no active references
        pFilter->ExternalRefs.Count = EX_RUNDOWN_ACTIVE;
        pFilter->cmdRundown.Count = EX_RUNDOWN_ACTIVE;

        // Query the compartment ID for this interface to use for the IP stack
        pFilter->InterfaceCompartmentID = GetInterfaceCompartmentID(&pFilter->InterfaceLuid);
        LogVerbose(DRIVER_DEFAULT, "Interface %!GUID! is in Compartment %u", &pFilter->InterfaceGuid, (ULONG)pFilter->InterfaceCompartmentID);

        // Make sure we are in the right compartment
        (VOID)otLwfSetCompartment(pFilter, &OriginalCompartmentID);

        // Register for address changed notifications
        NtStatus = 
            NotifyUnicastIpAddressChange(
                AF_INET6,
                otLwfAddressChangeCallback,
                pFilter,
                FALSE,
                &pFilter->AddressChangeHandle
                );

        // Revert the compartment, now that we have the table
        otLwfRevertCompartment(OriginalCompartmentID);

        if (!NT_SUCCESS(NtStatus))
        {
            LogError(DRIVER_DEFAULT, "NotifyUnicastIpAddressChange failed, %!STATUS!", NtStatus);
            Status = NDIS_STATUS_FAILURE;
            break;
        }

        // Add Filter to global list of Thread Filters
        NdisAcquireSpinLock(&FilterListLock);
        InsertTailList(&FilterModuleList, &pFilter->FilterModuleLink);
        NdisReleaseSpinLock(&FilterListLock);

        LogVerbose(DRIVER_DEFAULT, "Created Filter: %p", pFilter);

    } while (FALSE);

    // Clean up on failure
    if (Status != NDIS_STATUS_SUCCESS)
    {
        if (pFilter != NULL)
        {
            if (pFilter->AddressChangeHandle != NULL)
            {
                CancelMibChangeNotify2(pFilter->AddressChangeHandle);
                pFilter->AddressChangeHandle = NULL;
            }

            NdisFreeMemory(pFilter, 0, 0);
        }
    }

    LogFuncExitNDIS(DRIVER_DEFAULT, Status);

    return Status;
}