예제 #1
0
void 
otLwfTunUninitialize(
    _In_ PMS_FILTER pFilter
    )
{
    LogFuncEntry(DRIVER_DEFAULT);

    // Clean up worker thread
    if (pFilter->TunWorkerThread)
    {
        LogInfo(DRIVER_DEFAULT, "Stopping tunnel worker thread and waiting for it to complete.");

        // Send event to shutdown worker thread
        KeSetEvent(&pFilter->TunWorkerThreadStopEvent, 0, FALSE);

        // Wait for worker thread to finish
        KeWaitForSingleObject(
            pFilter->TunWorkerThread,
            Executive,
            KernelMode,
            FALSE,
            NULL
            );

        // Free worker thread
        ObDereferenceObject(pFilter->TunWorkerThread);
        pFilter->TunWorkerThread = NULL;

        LogInfo(DRIVER_DEFAULT, "Tunnel worker thread cleaned up.");
    }

    LogFuncExit(DRIVER_DEFAULT);
}
예제 #2
0
int TestFuncDebug()
{
	/* log the function entry log. */
	LogFuncEntry();

	LogTrace("Trace log %s %f", "Test", 1.066f);
	LogDebug("Debug level log" );
	LogInfo("Info level log %d" , 0);
	LogWarn("Warn level log" );
	LogError("Error level log" );
	LogFatal("Fatal level log" );

	if(1)
	{
		/* log the function exit. */
		LogFuncExit();
		return 0;
	}
	else
	{
		/* log the function exit. */
		LogFuncExit();
		return -1;
	}
	
}
예제 #3
0
void otPlatSettingsInit(otInstance *otCtx)
{
    NT_ASSERT(otCtx);
    PMS_FILTER pFilter = otCtxToFilter(otCtx);

    DECLARE_CONST_UNICODE_STRING(SubKeyName, L"OpenThread");

    OBJECT_ATTRIBUTES attributes;
    ULONG disposition;

    LogFuncEntry(DRIVER_DEFAULT);

    InitializeObjectAttributes(
        &attributes,
        (PUNICODE_STRING)&SubKeyName,
        OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
        pFilter->InterfaceRegKey,
        NULL);

    // Create/Open the 'OpenThread' sub key
    NTSTATUS status =
        ZwCreateKey(
            &pFilter->otSettingsRegKey,
            KEY_ALL_ACCESS,
            &attributes,
            0,
            NULL,
            REG_OPTION_NON_VOLATILE,
            &disposition);

    NT_ASSERT(NT_SUCCESS(status));
    if (!NT_SUCCESS(status))
    {
        LogError(DRIVER_DEFAULT, "ZwCreateKey for 'OpenThread' key failed, %!STATUS!", status);
    }

    LogFuncExit(DRIVER_DEFAULT);
}
예제 #4
0
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;
}
예제 #5
0
// Worker thread for processing all tunnel events
_Use_decl_annotations_
VOID
otLwfTunWorkerThread(
    PVOID   Context
    )
{
    PMS_FILTER pFilter = (PMS_FILTER)Context;
    NT_ASSERT(pFilter);

    LogFuncEntry(DRIVER_DEFAULT);

    PKEVENT WaitEvents[] = 
    { 
        &pFilter->TunWorkerThreadStopEvent,
        &pFilter->TunWorkerThreadAddressChangedEvent
    };

    LogFuncExit(DRIVER_DEFAULT);
    
    while (true)
    {
        // Wait for event to stop or process event to fire
        NTSTATUS status = 
            KeWaitForMultipleObjects(
                ARRAYSIZE(WaitEvents), 
                (PVOID*)WaitEvents, 
                WaitAny, 
                Executive, 
                KernelMode, 
                FALSE, 
                NULL, 
                NULL);

        // If it is the first event, then we are shutting down. Exit loop and terminate thread
        if (status == STATUS_WAIT_0)
        {
            LogInfo(DRIVER_DEFAULT, "Received tunnel worker thread shutdown event.");
            break;
        }
        else if (status == STATUS_WAIT_0 + 1) // TunWorkerThreadAddressChangedEvent fired
        {
            PVOID DataBuffer = NULL;
            const uint8_t* value_data_ptr = NULL;
            spinel_size_t value_data_len = 0;
            
            // Query the current addresses
            status = 
                otLwfCmdGetProp(
                    pFilter,
                    &DataBuffer,
                    SPINEL_PROP_IPV6_ADDRESS_TABLE,
                    SPINEL_DATATYPE_DATA_S,
                    &value_data_ptr,
                    &value_data_len);
            if (NT_SUCCESS(status))
            {
                uint32_t aNotifFlags = 0;
                otLwfTunAddressesUpdated(pFilter, value_data_ptr, value_data_len, &aNotifFlags);

                // Send notification
                if (aNotifFlags != 0)
                {
                    PFILTER_NOTIFICATION_ENTRY NotifEntry = FILTER_ALLOC_NOTIF(pFilter);
                    if (NotifEntry)
                    {
                        RtlZeroMemory(NotifEntry, sizeof(FILTER_NOTIFICATION_ENTRY));
                        NotifEntry->Notif.InterfaceGuid = pFilter->InterfaceGuid;
                        NotifEntry->Notif.NotifType = OTLWF_NOTIF_STATE_CHANGE;
                        NotifEntry->Notif.StateChangePayload.Flags = aNotifFlags;

                        otLwfIndicateNotification(NotifEntry);
                    }
                }
            }
            else
            {
                LogWarning(DRIVER_DEFAULT, "Failed to query addresses, %!STATUS!", status);
            }

            if (DataBuffer) FILTER_FREE_MEM(DataBuffer);
        }
        else
        {
            LogWarning(DRIVER_DEFAULT, "Unexpected wait result, %!STATUS!", status);
        }
    }

    PsTerminateSystemThread(STATUS_SUCCESS);
}
예제 #6
0
void otPlatSettingsWipe(otInstance *otCtx)
{
    NT_ASSERT(otCtx);
    PMS_FILTER pFilter = otCtxToFilter(otCtx);

    LogFuncEntry(DRIVER_DEFAULT);

    // Delete all subkeys of 'OpenThread'
    if (pFilter->otSettingsRegKey)
    {
        NTSTATUS status = STATUS_SUCCESS;
        ULONG index = 0;
        UCHAR keyInfo[sizeof(KEY_BASIC_INFORMATION) + 64];

        while (status == STATUS_SUCCESS)
        {
            ULONG size = sizeof(keyInfo);
            status =
                ZwEnumerateKey(
                    pFilter->otSettingsRegKey,
                    index,
                    KeyBasicInformation,
                    keyInfo,
                    size,
                    &size);

            bool deleted = false;
            if (NT_SUCCESS(status))
            {
                HANDLE subKey = NULL;
                OBJECT_ATTRIBUTES attributes;
                PKEY_BASIC_INFORMATION pKeyInfo = (PKEY_BASIC_INFORMATION)keyInfo;

                UNICODE_STRING subKeyName = 
                {
                    (USHORT)pKeyInfo->NameLength,
                    (USHORT)pKeyInfo->NameLength,
                    pKeyInfo->Name
                };

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

                // Open the sub key
                status =
                    ZwOpenKey(
                        &subKey,
                        KEY_ALL_ACCESS,
                        &attributes);

                if (NT_SUCCESS(status))
                {
                    // Delete the key
                    status = ZwDeleteKey(subKey);
                    if (!NT_SUCCESS(status))
                    {
                        LogError(DRIVER_DEFAULT, "ZwDeleteKey for subkey failed, %!STATUS!", status);
                    }
                    else
                    {
                        deleted = true;
                    }

                    // Close handle
                    ZwClose(subKey);
                }
                else
                {
                    LogError(DRIVER_DEFAULT, "ZwOpenKey for subkey failed, %!STATUS!", status);
                }
            }

            // Only increment index if we didn't delete
            if (!deleted)
            {
                index++;
            }
        }
    }

    LogFuncExit(DRIVER_DEFAULT);
}
예제 #7
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;
}