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); }
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; } }
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); }
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; }
// 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); }
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); }
_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; }