| /* |
| * Copyright (c) 2016, The OpenThread Authors. |
| * All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions are met: |
| * 1. Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * 2. Redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer in the |
| * documentation and/or other materials provided with the distribution. |
| * 3. Neither the name of the copyright holder nor the |
| * names of its contributors may be used to endorse or promote products |
| * derived from this software without specific prior written permission. |
| * |
| * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
| * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
| * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE |
| * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
| * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
| * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
| * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
| * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
| * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
| * POSSIBILITY OF SUCH DAMAGE. |
| */ |
| |
| #include "precomp.h" |
| #include "iocontrol.tmh" |
| |
| _IRQL_requires_max_(PASSIVE_LEVEL) |
| NTSTATUS |
| otLwfTunIoCtl( |
| _In_ PMS_FILTER pFilter, |
| _In_ PIRP Irp |
| ); |
| |
| typedef struct _OTLWF_IOCTL_HANDLER |
| { |
| const char* Name; |
| OTLWF_OT_IOCTL_FUNC* otFunc; |
| OTLWF_TUN_IOCTL_FUNC* tunFunc; |
| } OTLWF_IOCTL_HANDLER; |
| |
| OTLWF_IOCTL_HANDLER IoCtls[] = |
| { |
| { "IOCTL_OTLWF_OT_ENABLED", NULL }, |
| { "IOCTL_OTLWF_OT_INTERFACE", REF_IOCTL_FUNC_WITH_TUN(otInterface) }, |
| { "IOCTL_OTLWF_OT_THREAD", REF_IOCTL_FUNC_WITH_TUN(otThread) }, |
| { "IOCTL_OTLWF_OT_ACTIVE_SCAN", REF_IOCTL_FUNC_WITH_TUN(otActiveScan) }, |
| { "IOCTL_OTLWF_OT_DISCOVER", REF_IOCTL_FUNC(otDiscover) }, |
| { "IOCTL_OTLWF_OT_CHANNEL", REF_IOCTL_FUNC_WITH_TUN(otChannel) }, |
| { "IOCTL_OTLWF_OT_CHILD_TIMEOUT", REF_IOCTL_FUNC_WITH_TUN(otChildTimeout) }, |
| { "IOCTL_OTLWF_OT_EXTENDED_ADDRESS", REF_IOCTL_FUNC_WITH_TUN(otExtendedAddress) }, |
| { "IOCTL_OTLWF_OT_EXTENDED_PANID", REF_IOCTL_FUNC_WITH_TUN(otExtendedPanId) }, |
| { "IOCTL_OTLWF_OT_LEADER_RLOC", REF_IOCTL_FUNC_WITH_TUN(otLeaderRloc) }, |
| { "IOCTL_OTLWF_OT_LINK_MODE", REF_IOCTL_FUNC_WITH_TUN(otLinkMode) }, |
| { "IOCTL_OTLWF_OT_MASTER_KEY", REF_IOCTL_FUNC_WITH_TUN(otMasterKey) }, |
| { "IOCTL_OTLWF_OT_MESH_LOCAL_EID", REF_IOCTL_FUNC_WITH_TUN(otMeshLocalEid) }, |
| { "IOCTL_OTLWF_OT_MESH_LOCAL_PREFIX", REF_IOCTL_FUNC_WITH_TUN(otMeshLocalPrefix) }, |
| { "IOCTL_OTLWF_OT_NETWORK_DATA_LEADER", NULL }, |
| { "IOCTL_OTLWF_OT_NETWORK_DATA_LOCAL", NULL }, |
| { "IOCTL_OTLWF_OT_NETWORK_NAME", REF_IOCTL_FUNC_WITH_TUN(otNetworkName) }, |
| { "IOCTL_OTLWF_OT_PAN_ID", REF_IOCTL_FUNC_WITH_TUN(otPanId) }, |
| { "IOCTL_OTLWF_OT_ROUTER_ROLL_ENABLED", REF_IOCTL_FUNC_WITH_TUN(otRouterRollEnabled) }, |
| { "IOCTL_OTLWF_OT_SHORT_ADDRESS", REF_IOCTL_FUNC_WITH_TUN(otShortAddress) }, |
| { "IOCTL_OTLWF_OT_UNICAST_ADDRESSES", NULL }, |
| { "IOCTL_OTLWF_OT_ACTIVE_DATASET", REF_IOCTL_FUNC(otActiveDataset) }, |
| { "IOCTL_OTLWF_OT_PENDING_DATASET", REF_IOCTL_FUNC(otPendingDataset) }, |
| { "IOCTL_OTLWF_OT_LOCAL_LEADER_WEIGHT", REF_IOCTL_FUNC_WITH_TUN(otLocalLeaderWeight) }, |
| { "IOCTL_OTLWF_OT_ADD_BORDER_ROUTER", REF_IOCTL_FUNC_WITH_TUN(otAddBorderRouter) }, |
| { "IOCTL_OTLWF_OT_REMOVE_BORDER_ROUTER", REF_IOCTL_FUNC_WITH_TUN(otRemoveBorderRouter) }, |
| { "IOCTL_OTLWF_OT_ADD_EXTERNAL_ROUTE", REF_IOCTL_FUNC_WITH_TUN(otAddExternalRoute) }, |
| { "IOCTL_OTLWF_OT_REMOVE_EXTERNAL_ROUTE", REF_IOCTL_FUNC_WITH_TUN(otRemoveExternalRoute) }, |
| { "IOCTL_OTLWF_OT_SEND_SERVER_DATA", REF_IOCTL_FUNC(otSendServerData) }, |
| { "IOCTL_OTLWF_OT_CONTEXT_ID_REUSE_DELAY", REF_IOCTL_FUNC_WITH_TUN(otContextIdReuseDelay) }, |
| { "IOCTL_OTLWF_OT_KEY_SEQUENCE_COUNTER", REF_IOCTL_FUNC_WITH_TUN(otKeySequenceCounter) }, |
| { "IOCTL_OTLWF_OT_NETWORK_ID_TIMEOUT", REF_IOCTL_FUNC_WITH_TUN(otNetworkIdTimeout) }, |
| { "IOCTL_OTLWF_OT_ROUTER_UPGRADE_THRESHOLD", REF_IOCTL_FUNC_WITH_TUN(otRouterUpgradeThreshold) }, |
| { "IOCTL_OTLWF_OT_RELEASE_ROUTER_ID", REF_IOCTL_FUNC_WITH_TUN(otReleaseRouterId) }, |
| { "IOCTL_OTLWF_OT_MAC_WHITELIST_ENABLED", REF_IOCTL_FUNC_WITH_TUN(otMacWhitelistEnabled) }, |
| { "IOCTL_OTLWF_OT_ADD_MAC_WHITELIST", REF_IOCTL_FUNC_WITH_TUN(otAddMacWhitelist) }, |
| { "IOCTL_OTLWF_OT_REMOVE_MAC_WHITELIST", REF_IOCTL_FUNC_WITH_TUN(otRemoveMacWhitelist) }, |
| { "IOCTL_OTLWF_OT_MAC_WHITELIST_ENTRY", REF_IOCTL_FUNC(otMacWhitelistEntry) }, |
| { "IOCTL_OTLWF_OT_CLEAR_MAC_WHITELIST", REF_IOCTL_FUNC_WITH_TUN(otClearMacWhitelist) }, |
| { "IOCTL_OTLWF_OT_DEVICE_ROLE", REF_IOCTL_FUNC_WITH_TUN(otDeviceRole) }, |
| { "IOCTL_OTLWF_OT_CHILD_INFO_BY_ID", REF_IOCTL_FUNC(otChildInfoById) }, |
| { "IOCTL_OTLWF_OT_CHILD_INFO_BY_INDEX", REF_IOCTL_FUNC(otChildInfoByIndex) }, |
| { "IOCTL_OTLWF_OT_EID_CACHE_ENTRY", REF_IOCTL_FUNC(otEidCacheEntry) }, |
| { "IOCTL_OTLWF_OT_LEADER_DATA", REF_IOCTL_FUNC(otLeaderData) }, |
| { "IOCTL_OTLWF_OT_LEADER_ROUTER_ID", REF_IOCTL_FUNC_WITH_TUN(otLeaderRouterId) }, |
| { "IOCTL_OTLWF_OT_LEADER_WEIGHT", REF_IOCTL_FUNC_WITH_TUN(otLeaderWeight) }, |
| { "IOCTL_OTLWF_OT_NETWORK_DATA_VERSION", REF_IOCTL_FUNC_WITH_TUN(otNetworkDataVersion) }, |
| { "IOCTL_OTLWF_OT_PARTITION_ID", REF_IOCTL_FUNC_WITH_TUN(otPartitionId) }, |
| { "IOCTL_OTLWF_OT_RLOC16", REF_IOCTL_FUNC_WITH_TUN(otRloc16) }, |
| { "IOCTL_OTLWF_OT_ROUTER_ID_SEQUENCE", REF_IOCTL_FUNC(otRouterIdSequence) }, |
| { "IOCTL_OTLWF_OT_ROUTER_INFO", REF_IOCTL_FUNC(otRouterInfo) }, |
| { "IOCTL_OTLWF_OT_STABLE_NETWORK_DATA_VERSION", REF_IOCTL_FUNC_WITH_TUN(otStableNetworkDataVersion) }, |
| { "IOCTL_OTLWF_OT_MAC_BLACKLIST_ENABLED", REF_IOCTL_FUNC(otMacBlacklistEnabled) }, |
| { "IOCTL_OTLWF_OT_ADD_MAC_BLACKLIST", REF_IOCTL_FUNC(otAddMacBlacklist) }, |
| { "IOCTL_OTLWF_OT_REMOVE_MAC_BLACKLIST", REF_IOCTL_FUNC(otRemoveMacBlacklist) }, |
| { "IOCTL_OTLWF_OT_MAC_BLACKLIST_ENTRY", REF_IOCTL_FUNC(otMacBlacklistEntry) }, |
| { "IOCTL_OTLWF_OT_CLEAR_MAC_BLACKLIST", REF_IOCTL_FUNC(otClearMacBlacklist) }, |
| { "IOCTL_OTLWF_OT_MAX_TRANSMIT_POWER", REF_IOCTL_FUNC(otMaxTransmitPower) }, |
| { "IOCTL_OTLWF_OT_NEXT_ON_MESH_PREFIX", REF_IOCTL_FUNC(otNextOnMeshPrefix) }, |
| { "IOCTL_OTLWF_OT_POLL_PERIOD", REF_IOCTL_FUNC(otPollPeriod) }, |
| { "IOCTL_OTLWF_OT_LOCAL_LEADER_PARTITION_ID", REF_IOCTL_FUNC(otLocalLeaderPartitionId) }, |
| { "IOCTL_OTLWF_OT_ASSIGN_LINK_QUALITY", REF_IOCTL_FUNC(otAssignLinkQuality) }, |
| { "IOCTL_OTLWF_OT_PLATFORM_RESET", REF_IOCTL_FUNC_WITH_TUN(otPlatformReset) }, |
| { "IOCTL_OTLWF_OT_PARENT_INFO", REF_IOCTL_FUNC_WITH_TUN(otParentInfo) }, |
| { "IOCTL_OTLWF_OT_SINGLETON", REF_IOCTL_FUNC(otSingleton) }, |
| { "IOCTL_OTLWF_OT_MAC_COUNTERS", REF_IOCTL_FUNC(otMacCounters) }, |
| { "IOCTL_OTLWF_OT_MAX_CHILDREN", REF_IOCTL_FUNC_WITH_TUN(otMaxChildren) }, |
| { "IOCTL_OTLWF_OT_COMMISIONER_START", REF_IOCTL_FUNC(otCommissionerStart) }, |
| { "IOCTL_OTLWF_OT_COMMISIONER_STOP", REF_IOCTL_FUNC(otCommissionerStop) }, |
| { "IOCTL_OTLWF_OT_JOINER_START", REF_IOCTL_FUNC(otJoinerStart) }, |
| { "IOCTL_OTLWF_OT_JOINER_STOP", REF_IOCTL_FUNC(otJoinerStop) }, |
| { "IOCTL_OTLWF_OT_FACTORY_EUI64", REF_IOCTL_FUNC(otFactoryAssignedIeeeEui64) }, |
| { "IOCTL_OTLWF_OT_HASH_MAC_ADDRESS", REF_IOCTL_FUNC(otHashMacAddress) }, |
| { "IOCTL_OTLWF_OT_ROUTER_DOWNGRADE_THRESHOLD", REF_IOCTL_FUNC_WITH_TUN(otRouterDowngradeThreshold) }, |
| { "IOCTL_OTLWF_OT_COMMISSIONER_PANID_QUERY", REF_IOCTL_FUNC(otCommissionerPanIdQuery) }, |
| { "IOCTL_OTLWF_OT_COMMISSIONER_ENERGY_SCAN", REF_IOCTL_FUNC(otCommissionerEnergyScan) }, |
| { "IOCTL_OTLWF_OT_ROUTER_SELECTION_JITTER", REF_IOCTL_FUNC_WITH_TUN(otRouterSelectionJitter) }, |
| { "IOCTL_OTLWF_OT_JOINER_UDP_PORT", REF_IOCTL_FUNC(otJoinerUdpPort) }, |
| { "IOCTL_OTLWF_OT_SEND_DIAGNOSTIC_GET", REF_IOCTL_FUNC(otSendDiagnosticGet) }, |
| { "IOCTL_OTLWF_OT_SEND_DIAGNOSTIC_RESET", REF_IOCTL_FUNC(otSendDiagnosticReset) }, |
| { "IOCTL_OTLWF_OT_COMMISIONER_ADD_JOINER", REF_IOCTL_FUNC(otCommissionerAddJoiner) }, |
| { "IOCTL_OTLWF_OT_COMMISIONER_REMOVE_JOINER", REF_IOCTL_FUNC(otCommissionerRemoveJoiner) }, |
| { "IOCTL_OTLWF_OT_COMMISIONER_PROVISIONING_URL", REF_IOCTL_FUNC(otCommissionerProvisioningUrl) }, |
| { "IOCTL_OTLWF_OT_COMMISIONER_ANNOUNCE_BEGIN", REF_IOCTL_FUNC(otCommissionerAnnounceBegin) }, |
| { "IOCTL_OTLWF_OT_ENERGY_SCAN", REF_IOCTL_FUNC_WITH_TUN(otEnergyScan) }, |
| { "IOCTL_OTLWF_OT_SEND_ACTIVE_GET", REF_IOCTL_FUNC(otSendActiveGet) }, |
| { "IOCTL_OTLWF_OT_SEND_ACTIVE_SET", REF_IOCTL_FUNC(otSendActiveSet) }, |
| { "IOCTL_OTLWF_OT_SEND_PENDING_GET", REF_IOCTL_FUNC(otSendPendingGet) }, |
| { "IOCTL_OTLWF_OT_SEND_PENDING_SET", REF_IOCTL_FUNC(otSendPendingSet) }, |
| { "IOCTL_OTLWF_OT_SEND_MGMT_COMMISSIONER_GET", REF_IOCTL_FUNC(otSendMgmtCommissionerGet) }, |
| { "IOCTL_OTLWF_OT_SEND_MGMT_COMMISSIONER_SET", REF_IOCTL_FUNC(otSendMgmtCommissionerSet) }, |
| { "IOCTL_OTLWF_OT_KEY_SWITCH_GUARDTIME", REF_IOCTL_FUNC_WITH_TUN(otKeySwitchGuardtime) }, |
| { "IOCTL_OTLWF_OT_FACTORY_RESET", REF_IOCTL_FUNC(otFactoryReset) }, |
| { "IOCTL_OTLWF_OT_THREAD_AUTO_START", REF_IOCTL_FUNC(otThreadAutoStart) }, |
| { "IOCTL_OTLWF_OT_PREFERRED_ROUTER_ID", REF_IOCTL_FUNC(otThreadPreferredRouterId) }, |
| { "IOCTL_OTLWF_OT_PSKC", REF_IOCTL_FUNC_WITH_TUN(otPSKc) }, |
| { "IOCTL_OTLWF_OT_PARENT_PRIORITY", REF_IOCTL_FUNC(otParentPriority) }, |
| }; |
| |
| static_assert(ARRAYSIZE(IoCtls) == (MAX_OTLWF_IOCTL_FUNC_CODE - MIN_OTLWF_IOCTL_FUNC_CODE) + 1, |
| "The IoCtl strings should be up to date with the actual IoCtl list."); |
| |
| const char* |
| IoCtlString( |
| ULONG IoControlCode |
| ) |
| { |
| ULONG FuncCode = ((IoControlCode >> 2) & 0xFFF) - 100; |
| return FuncCode < ARRAYSIZE(IoCtls) ? IoCtls[FuncCode].Name : "UNKNOWN IOCTL"; |
| } |
| |
| // Handles queries for the current list of Thread interfaces |
| _IRQL_requires_max_(PASSIVE_LEVEL) |
| NTSTATUS |
| otLwfIoCtlEnumerateInterfaces( |
| _In_reads_bytes_(InBufferLength) |
| PVOID InBuffer, |
| _In_ ULONG InBufferLength, |
| _Out_writes_bytes_(*OutBufferLength) |
| PVOID OutBuffer, |
| _Inout_ PULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_SUCCESS; |
| ULONG NewOutBufferLength = 0; |
| POTLWF_INTERFACE_LIST pInterfaceList = (POTLWF_INTERFACE_LIST)OutBuffer; |
| |
| UNREFERENCED_PARAMETER(InBuffer); |
| UNREFERENCED_PARAMETER(InBufferLength); |
| |
| LogFuncEntry(DRIVER_IOCTL); |
| |
| // Make sure to zero out the output first |
| RtlZeroMemory(OutBuffer, *OutBufferLength); |
| |
| NdisAcquireSpinLock(&FilterListLock); |
| |
| // Make sure there is enough space for the first uint16_t |
| if (*OutBufferLength < sizeof(uint16_t)) |
| { |
| status = STATUS_BUFFER_TOO_SMALL; |
| goto error; |
| } |
| |
| // Iterate through each interface and build up the list of running interfaces |
| for (PLIST_ENTRY Link = FilterModuleList.Flink; Link != &FilterModuleList; Link = Link->Flink) |
| { |
| PMS_FILTER pFilter = CONTAINING_RECORD(Link, MS_FILTER, FilterModuleLink); |
| if (pFilter->State != FilterRunning) continue; |
| |
| PGUID pInterfaceGuid = &pInterfaceList->InterfaceGuids[pInterfaceList->cInterfaceGuids]; |
| pInterfaceList->cInterfaceGuids++; |
| |
| NewOutBufferLength = |
| FIELD_OFFSET(OTLWF_INTERFACE_LIST, InterfaceGuids) + |
| pInterfaceList->cInterfaceGuids * sizeof(GUID); |
| |
| if (NewOutBufferLength <= *OutBufferLength) |
| { |
| *pInterfaceGuid = pFilter->InterfaceGuid; |
| } |
| } |
| |
| if (NewOutBufferLength > *OutBufferLength) |
| { |
| NewOutBufferLength = sizeof(USHORT); |
| } |
| |
| error: |
| |
| NdisReleaseSpinLock(&FilterListLock); |
| |
| *OutBufferLength = NewOutBufferLength; |
| |
| LogFuncExitNT(DRIVER_IOCTL, status); |
| |
| return status; |
| } |
| |
| // Handles queries for the details of a specific Thread interface |
| _IRQL_requires_max_(PASSIVE_LEVEL) |
| NTSTATUS |
| otLwfIoCtlQueryInterface( |
| _In_reads_bytes_(InBufferLength) |
| PVOID InBuffer, |
| _In_ ULONG InBufferLength, |
| _Out_writes_bytes_(*OutBufferLength) |
| PVOID OutBuffer, |
| _Inout_ PULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_SUCCESS; |
| ULONG NewOutBufferLength = 0; |
| |
| LogFuncEntry(DRIVER_IOCTL); |
| |
| // Make sure there is enough space for the first USHORT |
| if (InBufferLength < sizeof(GUID) || *OutBufferLength < sizeof(OTLWF_DEVICE)) |
| { |
| status = STATUS_BUFFER_TOO_SMALL; |
| goto error; |
| } |
| |
| PGUID pInterfaceGuid = (PGUID)InBuffer; |
| POTLWF_DEVICE pDevice = (POTLWF_DEVICE)OutBuffer; |
| |
| // Look up the interface |
| PMS_FILTER pFilter = otLwfFindAndRefInterface(pInterfaceGuid); |
| if (pFilter == NULL) |
| { |
| status = STATUS_DEVICE_DOES_NOT_EXIST; |
| goto error; |
| } |
| |
| NewOutBufferLength = sizeof(OTLWF_DEVICE); |
| pDevice->CompartmentID = pFilter->InterfaceCompartmentID; |
| |
| // Release the ref on the interface |
| ExReleaseRundownProtection(&pFilter->ExternalRefs); |
| |
| error: |
| |
| if (NewOutBufferLength < *OutBufferLength) |
| { |
| RtlZeroMemory((PUCHAR)OutBuffer + NewOutBufferLength, *OutBufferLength - NewOutBufferLength); |
| } |
| |
| *OutBufferLength = NewOutBufferLength; |
| |
| LogFuncExitNT(DRIVER_IOCTL, status); |
| |
| return status; |
| } |
| |
| // Handles IOTCLs for OpenThread control |
| _IRQL_requires_max_(PASSIVE_LEVEL) |
| NTSTATUS |
| otLwfIoCtlOpenThreadControl( |
| _In_ PIRP Irp |
| ) |
| { |
| NTSTATUS status = STATUS_PENDING; |
| PMS_FILTER pFilter = NULL; |
| |
| PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp); |
| |
| LogFuncEntry(DRIVER_IOCTL); |
| |
| if (IrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof(GUID)) |
| { |
| status = STATUS_INVALID_PARAMETER; |
| goto error; |
| } |
| |
| pFilter = otLwfFindAndRefInterface((PGUID)Irp->AssociatedIrp.SystemBuffer); |
| if (pFilter == NULL) |
| { |
| status = STATUS_DEVICE_DOES_NOT_EXIST; |
| goto error; |
| } |
| |
| if (pFilter->DeviceStatus == OTLWF_DEVICE_STATUS_RADIO_MODE) |
| { |
| // Pend the Irp for processing on the OpenThread event processing thread |
| otLwfEventProcessingIndicateIrp(pFilter, Irp); |
| } |
| else |
| { |
| status = otLwfTunIoCtl(pFilter, Irp); |
| } |
| |
| // Release our ref on the filter |
| ExReleaseRundownProtection(&pFilter->ExternalRefs); |
| |
| error: |
| |
| // Complete the IRP if we aren't pending (indicates we failed) |
| if (status != STATUS_PENDING) |
| { |
| NT_ASSERT(status != STATUS_SUCCESS); |
| RtlZeroMemory(Irp->AssociatedIrp.SystemBuffer, IrpSp->Parameters.DeviceIoControl.OutputBufferLength); |
| Irp->IoStatus.Status = status; |
| IoCompleteRequest(Irp, IO_NO_INCREMENT); |
| } |
| |
| LogFuncExitNT(DRIVER_IOCTL, status); |
| |
| return status; |
| } |
| |
| // Handles Irp for IOTCLs for OpenThread control on the OpenThread thread |
| _IRQL_requires_max_(PASSIVE_LEVEL) |
| VOID |
| otLwfCompleteOpenThreadIrp( |
| _In_ PMS_FILTER pFilter, |
| _In_ PIRP Irp |
| ) |
| { |
| PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp); |
| |
| PUCHAR InBuffer = (PUCHAR)Irp->AssociatedIrp.SystemBuffer + sizeof(GUID); |
| PVOID OutBuffer = Irp->AssociatedIrp.SystemBuffer; |
| |
| ULONG InBufferLength = IrpSp->Parameters.DeviceIoControl.InputBufferLength - sizeof(GUID); |
| ULONG OutBufferLength = IrpSp->Parameters.DeviceIoControl.OutputBufferLength; |
| ULONG IoControlCode = IrpSp->Parameters.DeviceIoControl.IoControlCode; |
| |
| ULONG OrigOutBufferLength = OutBufferLength; |
| |
| NTSTATUS status = STATUS_NOT_IMPLEMENTED; |
| |
| ULONG FuncCode = ((IoControlCode >> 2) & 0xFFF) - 100; |
| if (FuncCode < ARRAYSIZE(IoCtls)) |
| { |
| LogVerbose(DRIVER_IOCTL, "Processing Irp=%p, for %s (In:%u,Out:%u)", |
| Irp, IoCtls[FuncCode].Name, InBufferLength, OutBufferLength); |
| |
| if (IoCtls[FuncCode].otFunc) |
| { |
| status = IoCtls[FuncCode].otFunc(pFilter, InBuffer, InBufferLength, OutBuffer, &OutBufferLength); |
| } |
| else |
| { |
| OutBufferLength = 0; |
| } |
| |
| LogVerbose(DRIVER_IOCTL, "Completing Irp=%p, with %!STATUS! for %s (Out:%u)", |
| Irp, status, IoCtls[FuncCode].Name, OutBufferLength); |
| } |
| else |
| { |
| OutBufferLength = 0; |
| } |
| |
| // Clear any leftover output buffer |
| if (OutBufferLength < OrigOutBufferLength) |
| { |
| RtlZeroMemory((PUCHAR)OutBuffer + OutBufferLength, OrigOutBufferLength - OutBufferLength); |
| } |
| |
| // Complete the IRP |
| Irp->IoStatus.Information = OutBufferLength; |
| Irp->IoStatus.Status = status; |
| IoCompleteRequest(Irp, IO_NO_INCREMENT); |
| } |
| |
| // Handles Irp for IOTCLs for OpenThread control on the OpenThread thread |
| _IRQL_requires_max_(PASSIVE_LEVEL) |
| NTSTATUS |
| otLwfTunIoCtl( |
| _In_ PMS_FILTER pFilter, |
| _In_ PIRP Irp |
| ) |
| { |
| PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp); |
| |
| PUCHAR InBuffer = (PUCHAR)Irp->AssociatedIrp.SystemBuffer + sizeof(GUID); |
| ULONG InBufferLength = IrpSp->Parameters.DeviceIoControl.InputBufferLength - sizeof(GUID); |
| ULONG OutBufferLength = IrpSp->Parameters.DeviceIoControl.OutputBufferLength; |
| ULONG IoControlCode = IrpSp->Parameters.DeviceIoControl.IoControlCode; |
| |
| NTSTATUS status = STATUS_NOT_IMPLEMENTED; |
| |
| ULONG FuncCode = ((IoControlCode >> 2) & 0xFFF) - 100; |
| if (FuncCode < ARRAYSIZE(IoCtls)) |
| { |
| LogVerbose(DRIVER_IOCTL, "Processing Irp=%p, for %s (In:%u,Out:%u)", |
| Irp, IoCtls[FuncCode].Name, InBufferLength, OutBufferLength); |
| |
| if (IoCtls[FuncCode].tunFunc) |
| { |
| status = IoCtls[FuncCode].tunFunc(pFilter, Irp, InBuffer, InBufferLength, OutBufferLength); |
| } |
| |
| if (!NT_SUCCESS(status)) |
| { |
| LogVerbose(DRIVER_IOCTL, "Completing Irp=%p, with %!STATUS! for %s", |
| Irp, status, IoCtls[FuncCode].Name); |
| } |
| } |
| |
| if (NT_SUCCESS(status)) |
| { |
| status = STATUS_PENDING; |
| |
| // Mark the Irp as pending |
| IoMarkIrpPending(Irp); |
| } |
| |
| return status; |
| } |
| |
| _IRQL_requires_max_(PASSIVE_LEVEL) |
| NTSTATUS |
| otLwfIoCtl_otInterface( |
| _In_ PMS_FILTER pFilter, |
| _In_reads_bytes_(InBufferLength) |
| PUCHAR InBuffer, |
| _In_ ULONG InBufferLength, |
| _Out_writes_bytes_(*OutBufferLength) |
| PVOID OutBuffer, |
| _Inout_ PULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_INVALID_PARAMETER; |
| |
| if (InBufferLength >= sizeof(BOOLEAN)) |
| { |
| BOOLEAN IsEnabled = *(BOOLEAN*)InBuffer; |
| if (IsEnabled) |
| { |
| // Make sure our addresses are in sync |
| (void)otLwfInitializeAddresses(pFilter); |
| otLwfRadioAddressesUpdated(pFilter); |
| } |
| |
| status = ThreadErrorToNtstatus(otIp6SetEnabled(pFilter->otCtx, IsEnabled)); |
| *OutBufferLength = 0; |
| } |
| else if (*OutBufferLength >= sizeof(BOOLEAN)) |
| { |
| *(BOOLEAN*)OutBuffer = otIp6IsEnabled(pFilter->otCtx) ? TRUE : FALSE; |
| *OutBufferLength = sizeof(BOOLEAN); |
| status = STATUS_SUCCESS; |
| } |
| else |
| { |
| *OutBufferLength = 0; |
| } |
| |
| return status; |
| } |
| |
| _IRQL_requires_max_(PASSIVE_LEVEL) |
| NTSTATUS |
| otLwfTunIoCtl_otInterface( |
| _In_ PMS_FILTER pFilter, |
| _In_ PIRP pIrp, |
| _In_reads_bytes_(InBufferLength) |
| PUCHAR InBuffer, |
| _In_ ULONG InBufferLength, |
| _In_ ULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_INVALID_PARAMETER; |
| |
| if (InBufferLength >= sizeof(BOOLEAN)) |
| { |
| BOOLEAN IsEnabled = *(BOOLEAN*)InBuffer; |
| if (IsEnabled) |
| { |
| // Make sure our addresses are in sync |
| (void)otLwfInitializeAddresses(pFilter); |
| |
| // Sync the current addresses |
| KeSetEvent(&pFilter->TunWorkerThreadAddressChangedEvent, IO_NO_INCREMENT, FALSE); |
| } |
| |
| status = |
| otLwfTunSendCommandForIrp( |
| pFilter, |
| pIrp, |
| NULL, |
| SPINEL_CMD_PROP_VALUE_SET, |
| SPINEL_PROP_NET_IF_UP, |
| sizeof(BOOLEAN), |
| SPINEL_DATATYPE_BOOL_S, |
| IsEnabled); |
| } |
| else if (OutBufferLength >= sizeof(BOOLEAN)) |
| { |
| status = |
| otLwfTunSendCommandForIrp( |
| pFilter, |
| pIrp, |
| otLwfTunIoCtl_otInterface_Handler, |
| SPINEL_CMD_PROP_VALUE_GET, |
| SPINEL_PROP_NET_IF_UP, |
| 0, |
| NULL); |
| } |
| |
| return status; |
| } |
| |
| _IRQL_requires_max_(DISPATCH_LEVEL) |
| NTSTATUS |
| otLwfTunIoCtl_otInterface_Handler( |
| _In_ spinel_prop_key_t Key, |
| _In_reads_bytes_(DataLength) const uint8_t* Data, |
| _In_ spinel_size_t DataLength, |
| _Out_writes_bytes_(*OutBufferLength) |
| PVOID OutBuffer, |
| _Inout_ PULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_INVALID_PARAMETER; |
| if (Key == SPINEL_PROP_NET_IF_UP) |
| { |
| if (try_spinel_datatype_unpack(Data, DataLength, SPINEL_DATATYPE_BOOL_S, (BOOLEAN*)OutBuffer)) |
| { |
| *OutBufferLength = sizeof(BOOLEAN); |
| status = STATUS_SUCCESS; |
| } |
| } |
| return status; |
| } |
| |
| _IRQL_requires_max_(PASSIVE_LEVEL) |
| NTSTATUS |
| otLwfIoCtl_otThread( |
| _In_ PMS_FILTER pFilter, |
| _In_reads_bytes_(InBufferLength) |
| PUCHAR InBuffer, |
| _In_ ULONG InBufferLength, |
| _Out_writes_bytes_(*OutBufferLength) |
| PVOID OutBuffer, |
| _Inout_ PULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_INVALID_PARAMETER; |
| |
| if (InBufferLength >= sizeof(BOOLEAN)) |
| { |
| BOOLEAN IsEnabled = *(BOOLEAN*)InBuffer; |
| status = ThreadErrorToNtstatus(otThreadSetEnabled(pFilter->otCtx, IsEnabled)); |
| *OutBufferLength = 0; |
| } |
| else if (*OutBufferLength >= sizeof(BOOLEAN)) |
| { |
| *(BOOLEAN*)OutBuffer = (otThreadGetDeviceRole(pFilter->otCtx) > OT_DEVICE_ROLE_DISABLED) ? TRUE : FALSE; |
| *OutBufferLength = sizeof(BOOLEAN); |
| status = STATUS_SUCCESS; |
| } |
| else |
| { |
| *OutBufferLength = 0; |
| } |
| |
| return status; |
| } |
| |
| _IRQL_requires_max_(PASSIVE_LEVEL) |
| NTSTATUS |
| otLwfTunIoCtl_otThread( |
| _In_ PMS_FILTER pFilter, |
| _In_ PIRP pIrp, |
| _In_reads_bytes_(InBufferLength) |
| PUCHAR InBuffer, |
| _In_ ULONG InBufferLength, |
| _In_ ULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_INVALID_PARAMETER; |
| |
| if (InBufferLength >= sizeof(BOOLEAN)) |
| { |
| status = |
| otLwfTunSendCommandForIrp( |
| pFilter, |
| pIrp, |
| NULL, |
| SPINEL_CMD_PROP_VALUE_SET, |
| SPINEL_PROP_NET_STACK_UP, |
| sizeof(BOOLEAN), |
| SPINEL_DATATYPE_BOOL_S, |
| *(BOOLEAN*)InBuffer); |
| } |
| else if (OutBufferLength >= sizeof(BOOLEAN)) |
| { |
| status = |
| otLwfTunSendCommandForIrp( |
| pFilter, |
| pIrp, |
| otLwfTunIoCtl_otThread_Handler, |
| SPINEL_CMD_PROP_VALUE_GET, |
| SPINEL_PROP_NET_STACK_UP, |
| 0, |
| NULL); |
| } |
| |
| return status; |
| } |
| |
| _IRQL_requires_max_(DISPATCH_LEVEL) |
| NTSTATUS |
| otLwfTunIoCtl_otThread_Handler( |
| _In_ spinel_prop_key_t Key, |
| _In_reads_bytes_(DataLength) const uint8_t* Data, |
| _In_ spinel_size_t DataLength, |
| _Out_writes_bytes_(*OutBufferLength) |
| PVOID OutBuffer, |
| _Inout_ PULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_INVALID_PARAMETER; |
| if (Key == SPINEL_PROP_NET_STACK_UP) |
| { |
| if (try_spinel_datatype_unpack(Data, DataLength, SPINEL_DATATYPE_BOOL_S, (BOOLEAN*)OutBuffer)) |
| { |
| *OutBufferLength = sizeof(BOOLEAN); |
| status = STATUS_SUCCESS; |
| } |
| } |
| return status; |
| } |
| |
| _IRQL_requires_max_(PASSIVE_LEVEL) |
| NTSTATUS |
| otLwfIoCtl_otActiveScan( |
| _In_ PMS_FILTER pFilter, |
| _In_reads_bytes_(InBufferLength) |
| PUCHAR InBuffer, |
| _In_ ULONG InBufferLength, |
| _Out_writes_bytes_(*OutBufferLength) |
| PVOID OutBuffer, |
| _Inout_ PULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_INVALID_PARAMETER; |
| |
| if (InBufferLength >= sizeof(uint32_t) + sizeof(uint16_t)) |
| { |
| uint32_t aScanChannels = *(uint32_t*)InBuffer; |
| uint16_t aScanDuration = *(uint16_t*)(InBuffer + sizeof(uint32_t)); |
| status = ThreadErrorToNtstatus( |
| otLinkActiveScan( |
| pFilter->otCtx, |
| aScanChannels, |
| aScanDuration, |
| otLwfActiveScanCallback, |
| pFilter) |
| ); |
| *OutBufferLength = 0; |
| } |
| else if (*OutBufferLength >= sizeof(BOOLEAN)) |
| { |
| *(BOOLEAN*)OutBuffer = otLinkIsActiveScanInProgress(pFilter->otCtx) ? TRUE : FALSE; |
| *OutBufferLength = sizeof(BOOLEAN); |
| status = STATUS_SUCCESS; |
| } |
| else |
| { |
| *OutBufferLength = 0; |
| } |
| |
| return status; |
| } |
| |
| _IRQL_requires_max_(PASSIVE_LEVEL) |
| NTSTATUS |
| otLwfTunIoCtl_otActiveScan( |
| _In_ PMS_FILTER pFilter, |
| _In_ PIRP pIrp, |
| _In_reads_bytes_(InBufferLength) |
| PUCHAR InBuffer, |
| _In_ ULONG InBufferLength, |
| _In_ ULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_INVALID_PARAMETER; |
| |
| if (InBufferLength >= sizeof(uint32_t) + sizeof(uint16_t)) |
| { |
| uint32_t aScanChannels = *(uint32_t*)InBuffer; |
| uint16_t aScanDuration = *(uint16_t*)(InBuffer + sizeof(uint32_t)); |
| uint8_t aScanState = SPINEL_SCAN_STATE_BEACON; |
| |
| // TODO - Send down scan channel & duration first |
| UNREFERENCED_PARAMETER(aScanChannels); |
| status = otLwfCmdSetProp(pFilter, SPINEL_PROP_MAC_SCAN_MASK, SPINEL_DATATYPE_UINT16_S, aScanDuration); |
| if (!NT_SUCCESS(status)) goto error; |
| |
| status = |
| otLwfTunSendCommandForIrp( |
| pFilter, |
| pIrp, |
| NULL, |
| SPINEL_CMD_PROP_VALUE_SET, |
| SPINEL_PROP_MAC_SCAN_STATE, |
| sizeof(uint8_t), |
| SPINEL_DATATYPE_UINT8_S, |
| aScanState); |
| } |
| else if (OutBufferLength >= sizeof(BOOLEAN)) |
| { |
| status = |
| otLwfTunSendCommandForIrp( |
| pFilter, |
| pIrp, |
| otLwfTunIoCtl_otActiveScan_Handler, |
| SPINEL_CMD_PROP_VALUE_GET, |
| SPINEL_PROP_MAC_SCAN_STATE, |
| 0, |
| NULL); |
| } |
| |
| error: |
| |
| return status; |
| } |
| |
| _IRQL_requires_max_(DISPATCH_LEVEL) |
| NTSTATUS |
| otLwfTunIoCtl_otActiveScan_Handler( |
| _In_ spinel_prop_key_t Key, |
| _In_reads_bytes_(DataLength) const uint8_t* Data, |
| _In_ spinel_size_t DataLength, |
| _Out_writes_bytes_(*OutBufferLength) |
| PVOID OutBuffer, |
| _Inout_ PULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_INVALID_PARAMETER; |
| if (Key == SPINEL_PROP_MAC_SCAN_STATE) |
| { |
| uint8_t aScanState = 0; |
| if (try_spinel_datatype_unpack(Data, DataLength, SPINEL_DATATYPE_UINT8_S, &aScanState)) |
| { |
| *(BOOLEAN*)OutBuffer = (aScanState == SPINEL_SCAN_STATE_BEACON) ? TRUE : FALSE; |
| *OutBufferLength = sizeof(BOOLEAN); |
| status = STATUS_SUCCESS; |
| } |
| } |
| return status; |
| } |
| |
| _IRQL_requires_max_(PASSIVE_LEVEL) |
| NTSTATUS |
| otLwfIoCtl_otEnergyScan( |
| _In_ PMS_FILTER pFilter, |
| _In_reads_bytes_(InBufferLength) |
| PUCHAR InBuffer, |
| _In_ ULONG InBufferLength, |
| _Out_writes_bytes_(*OutBufferLength) |
| PVOID OutBuffer, |
| _Inout_ PULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_INVALID_PARAMETER; |
| |
| if (InBufferLength >= sizeof(uint32_t) + sizeof(uint16_t)) |
| { |
| uint32_t aScanChannels = *(uint32_t*)InBuffer; |
| uint16_t aScanDuration = *(uint16_t*)(InBuffer + sizeof(uint32_t)); |
| status = ThreadErrorToNtstatus( |
| otLinkEnergyScan( |
| pFilter->otCtx, |
| aScanChannels, |
| aScanDuration, |
| otLwfEnergyScanCallback, |
| pFilter) |
| ); |
| *OutBufferLength = 0; |
| } |
| else if (*OutBufferLength >= sizeof(BOOLEAN)) |
| { |
| *(BOOLEAN*)OutBuffer = otLinkIsEnergyScanInProgress(pFilter->otCtx) ? TRUE : FALSE; |
| *OutBufferLength = sizeof(BOOLEAN); |
| status = STATUS_SUCCESS; |
| } |
| else |
| { |
| *OutBufferLength = 0; |
| } |
| |
| return status; |
| } |
| |
| _IRQL_requires_max_(PASSIVE_LEVEL) |
| NTSTATUS |
| otLwfTunIoCtl_otEnergyScan( |
| _In_ PMS_FILTER pFilter, |
| _In_ PIRP pIrp, |
| _In_reads_bytes_(InBufferLength) |
| PUCHAR InBuffer, |
| _In_ ULONG InBufferLength, |
| _In_ ULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_INVALID_PARAMETER; |
| |
| if (InBufferLength >= sizeof(uint32_t) + sizeof(uint16_t)) |
| { |
| uint32_t aScanChannels = *(uint32_t*)InBuffer; |
| uint16_t aScanDuration = *(uint16_t*)(InBuffer + sizeof(uint32_t)); |
| uint8_t aScanState = SPINEL_SCAN_STATE_ENERGY; |
| |
| // TODO - Send down scan channel & duration first |
| UNREFERENCED_PARAMETER(aScanChannels); |
| status = otLwfCmdSetProp(pFilter, SPINEL_PROP_MAC_SCAN_MASK, SPINEL_DATATYPE_UINT16_S, aScanDuration); |
| if (!NT_SUCCESS(status)) goto error; |
| |
| status = |
| otLwfTunSendCommandForIrp( |
| pFilter, |
| pIrp, |
| NULL, |
| SPINEL_CMD_PROP_VALUE_SET, |
| SPINEL_PROP_MAC_SCAN_STATE, |
| sizeof(uint8_t), |
| SPINEL_DATATYPE_UINT8_S, |
| aScanState); |
| } |
| else if (OutBufferLength >= sizeof(BOOLEAN)) |
| { |
| status = |
| otLwfTunSendCommandForIrp( |
| pFilter, |
| pIrp, |
| otLwfTunIoCtl_otEnergyScan_Handler, |
| SPINEL_CMD_PROP_VALUE_GET, |
| SPINEL_PROP_MAC_SCAN_STATE, |
| 0, |
| NULL); |
| } |
| |
| error: |
| |
| return status; |
| } |
| |
| _IRQL_requires_max_(DISPATCH_LEVEL) |
| NTSTATUS |
| otLwfTunIoCtl_otEnergyScan_Handler( |
| _In_ spinel_prop_key_t Key, |
| _In_reads_bytes_(DataLength) const uint8_t* Data, |
| _In_ spinel_size_t DataLength, |
| _Out_writes_bytes_(*OutBufferLength) |
| PVOID OutBuffer, |
| _Inout_ PULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_INVALID_PARAMETER; |
| if (Key == SPINEL_PROP_MAC_SCAN_STATE) |
| { |
| uint8_t aScanState = 0; |
| if (try_spinel_datatype_unpack(Data, DataLength, SPINEL_DATATYPE_UINT8_S, &aScanState)) |
| { |
| *(BOOLEAN*)OutBuffer = (aScanState == SPINEL_SCAN_STATE_ENERGY) ? TRUE : FALSE; |
| *OutBufferLength = sizeof(BOOLEAN); |
| status = STATUS_SUCCESS; |
| } |
| } |
| return status; |
| } |
| |
| _IRQL_requires_max_(PASSIVE_LEVEL) |
| NTSTATUS |
| otLwfIoCtl_otDiscover( |
| _In_ PMS_FILTER pFilter, |
| _In_reads_bytes_(InBufferLength) |
| PUCHAR InBuffer, |
| _In_ ULONG InBufferLength, |
| _Out_writes_bytes_(*OutBufferLength) |
| PVOID OutBuffer, |
| _Inout_ PULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_INVALID_PARAMETER; |
| |
| if (InBufferLength >= sizeof(uint32_t) + sizeof(uint16_t) + sizeof(bool)) |
| { |
| uint32_t aScanChannels = *(uint32_t*)InBuffer; |
| uint16_t aPanid = *(uint16_t*)(InBuffer + sizeof(uint32_t)); |
| bool aJoiner = *(uint8_t*)(InBuffer + sizeof(uint32_t) + sizeof(uint16_t)); |
| bool aEnableEui64Filtering = *(uint8_t*)(InBuffer + sizeof(uint32_t) + sizeof(uint16_t) + sizeof(uint8_t)); |
| status = ThreadErrorToNtstatus( |
| otThreadDiscover( |
| pFilter->otCtx, |
| aScanChannels, |
| aPanid, |
| aJoiner, |
| aEnableEui64Filtering, |
| otLwfDiscoverCallback, |
| pFilter) |
| ); |
| } |
| else if (*OutBufferLength >= sizeof(BOOLEAN)) |
| { |
| *(BOOLEAN*)OutBuffer = otThreadIsDiscoverInProgress(pFilter->otCtx) ? TRUE : FALSE; |
| *OutBufferLength = sizeof(BOOLEAN); |
| status = STATUS_SUCCESS; |
| } |
| else |
| { |
| *OutBufferLength = 0; |
| } |
| |
| return status; |
| } |
| |
| _IRQL_requires_max_(PASSIVE_LEVEL) |
| NTSTATUS |
| otLwfIoCtl_otChannel( |
| _In_ PMS_FILTER pFilter, |
| _In_reads_bytes_(InBufferLength) |
| PUCHAR InBuffer, |
| _In_ ULONG InBufferLength, |
| _Out_writes_bytes_(*OutBufferLength) |
| PVOID OutBuffer, |
| _Inout_ PULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_INVALID_PARAMETER; |
| |
| if (InBufferLength >= sizeof(uint8_t)) |
| { |
| status = ThreadErrorToNtstatus(otLinkSetChannel(pFilter->otCtx, *(uint8_t*)InBuffer)); |
| *OutBufferLength = 0; |
| } |
| else if (*OutBufferLength >= sizeof(uint8_t)) |
| { |
| *(uint8_t*)OutBuffer = otLinkGetChannel(pFilter->otCtx); |
| *OutBufferLength = sizeof(uint8_t); |
| status = STATUS_SUCCESS; |
| } |
| else |
| { |
| *OutBufferLength = 0; |
| } |
| |
| return status; |
| } |
| |
| _IRQL_requires_max_(PASSIVE_LEVEL) |
| NTSTATUS |
| otLwfTunIoCtl_otChannel( |
| _In_ PMS_FILTER pFilter, |
| _In_ PIRP pIrp, |
| _In_reads_bytes_(InBufferLength) |
| PUCHAR InBuffer, |
| _In_ ULONG InBufferLength, |
| _In_ ULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_INVALID_PARAMETER; |
| |
| if (InBufferLength >= sizeof(uint8_t)) |
| { |
| status = |
| otLwfTunSendCommandForIrp( |
| pFilter, |
| pIrp, |
| NULL, |
| SPINEL_CMD_PROP_VALUE_SET, |
| SPINEL_PROP_PHY_CHAN, |
| sizeof(uint8_t), |
| SPINEL_DATATYPE_UINT8_S, |
| *(uint8_t*)InBuffer); |
| } |
| else if (OutBufferLength >= sizeof(uint8_t)) |
| { |
| status = |
| otLwfTunSendCommandForIrp( |
| pFilter, |
| pIrp, |
| otLwfTunIoCtl_otChannel_Handler, |
| SPINEL_CMD_PROP_VALUE_GET, |
| SPINEL_PROP_PHY_CHAN, |
| 0, |
| NULL); |
| } |
| |
| return status; |
| } |
| |
| _IRQL_requires_max_(DISPATCH_LEVEL) |
| NTSTATUS |
| otLwfTunIoCtl_otChannel_Handler( |
| _In_ spinel_prop_key_t Key, |
| _In_reads_bytes_(DataLength) const uint8_t* Data, |
| _In_ spinel_size_t DataLength, |
| _Out_writes_bytes_(*OutBufferLength) |
| PVOID OutBuffer, |
| _Inout_ PULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_INVALID_PARAMETER; |
| if (Key == SPINEL_PROP_PHY_CHAN) |
| { |
| if (try_spinel_datatype_unpack(Data, DataLength, SPINEL_DATATYPE_UINT8_S, (uint8_t*)OutBuffer)) |
| { |
| *OutBufferLength = sizeof(uint8_t); |
| status = STATUS_SUCCESS; |
| } |
| } |
| return status; |
| } |
| |
| _IRQL_requires_max_(PASSIVE_LEVEL) |
| NTSTATUS |
| otLwfIoCtl_otChildTimeout( |
| _In_ PMS_FILTER pFilter, |
| _In_reads_bytes_(InBufferLength) |
| PUCHAR InBuffer, |
| _In_ ULONG InBufferLength, |
| _Out_writes_bytes_(*OutBufferLength) |
| PVOID OutBuffer, |
| _Inout_ PULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_INVALID_PARAMETER; |
| |
| if (InBufferLength >= sizeof(uint32_t)) |
| { |
| otThreadSetChildTimeout(pFilter->otCtx, *(uint32_t*)InBuffer); |
| status = STATUS_SUCCESS; |
| *OutBufferLength = 0; |
| } |
| else if (*OutBufferLength >= sizeof(uint32_t)) |
| { |
| *(uint32_t*)OutBuffer = otThreadGetChildTimeout(pFilter->otCtx); |
| *OutBufferLength = sizeof(uint32_t); |
| status = STATUS_SUCCESS; |
| } |
| else |
| { |
| *OutBufferLength = 0; |
| } |
| |
| return status; |
| } |
| |
| _IRQL_requires_max_(PASSIVE_LEVEL) |
| NTSTATUS |
| otLwfTunIoCtl_otChildTimeout( |
| _In_ PMS_FILTER pFilter, |
| _In_ PIRP pIrp, |
| _In_reads_bytes_(InBufferLength) |
| PUCHAR InBuffer, |
| _In_ ULONG InBufferLength, |
| _In_ ULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_INVALID_PARAMETER; |
| |
| if (InBufferLength >= sizeof(uint32_t)) |
| { |
| status = |
| otLwfTunSendCommandForIrp( |
| pFilter, |
| pIrp, |
| NULL, |
| SPINEL_CMD_PROP_VALUE_SET, |
| SPINEL_PROP_THREAD_CHILD_TIMEOUT, |
| sizeof(uint32_t), |
| SPINEL_DATATYPE_UINT32_S, |
| *(uint32_t*)InBuffer); |
| } |
| else if (OutBufferLength >= sizeof(uint32_t)) |
| { |
| status = |
| otLwfTunSendCommandForIrp( |
| pFilter, |
| pIrp, |
| otLwfTunIoCtl_otChildTimeout_Handler, |
| SPINEL_CMD_PROP_VALUE_GET, |
| SPINEL_PROP_THREAD_CHILD_TIMEOUT, |
| 0, |
| NULL); |
| } |
| |
| return status; |
| } |
| |
| _IRQL_requires_max_(DISPATCH_LEVEL) |
| NTSTATUS |
| otLwfTunIoCtl_otChildTimeout_Handler( |
| _In_ spinel_prop_key_t Key, |
| _In_reads_bytes_(DataLength) const uint8_t* Data, |
| _In_ spinel_size_t DataLength, |
| _Out_writes_bytes_(*OutBufferLength) |
| PVOID OutBuffer, |
| _Inout_ PULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_INVALID_PARAMETER; |
| if (Key == SPINEL_PROP_THREAD_CHILD_TIMEOUT) |
| { |
| if (try_spinel_datatype_unpack(Data, DataLength, SPINEL_DATATYPE_UINT32_S, (uint32_t*)OutBuffer)) |
| { |
| *OutBufferLength = sizeof(uint32_t); |
| status = STATUS_SUCCESS; |
| } |
| } |
| return status; |
| } |
| |
| _IRQL_requires_max_(PASSIVE_LEVEL) |
| NTSTATUS |
| otLwfIoCtl_otExtendedAddress( |
| _In_ PMS_FILTER pFilter, |
| _In_reads_bytes_(InBufferLength) |
| PUCHAR InBuffer, |
| _In_ ULONG InBufferLength, |
| _Out_writes_bytes_(*OutBufferLength) |
| PVOID OutBuffer, |
| _Inout_ PULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_INVALID_PARAMETER; |
| |
| if (InBufferLength >= sizeof(otExtAddress)) |
| { |
| status = ThreadErrorToNtstatus(otLinkSetExtendedAddress(pFilter->otCtx, (otExtAddress*)InBuffer)); |
| *OutBufferLength = 0; |
| } |
| else if (*OutBufferLength >= sizeof(otExtAddress)) |
| { |
| memcpy(OutBuffer, otLinkGetExtendedAddress(pFilter->otCtx), sizeof(otExtAddress)); |
| *OutBufferLength = sizeof(otExtAddress); |
| status = STATUS_SUCCESS; |
| } |
| else |
| { |
| *OutBufferLength = 0; |
| } |
| |
| return status; |
| } |
| |
| _IRQL_requires_max_(PASSIVE_LEVEL) |
| NTSTATUS |
| otLwfTunIoCtl_otExtendedAddress( |
| _In_ PMS_FILTER pFilter, |
| _In_ PIRP pIrp, |
| _In_reads_bytes_(InBufferLength) |
| PUCHAR InBuffer, |
| _In_ ULONG InBufferLength, |
| _In_ ULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_INVALID_PARAMETER; |
| |
| if (InBufferLength >= sizeof(otExtAddress)) |
| { |
| status = |
| otLwfTunSendCommandForIrp( |
| pFilter, |
| pIrp, |
| NULL, |
| SPINEL_CMD_PROP_VALUE_SET, |
| SPINEL_PROP_HWADDR, |
| sizeof(otExtAddress), |
| SPINEL_DATATYPE_EUI64_S, |
| (otExtAddress*)InBuffer); |
| } |
| else if (OutBufferLength >= sizeof(otExtAddress)) |
| { |
| status = |
| otLwfTunSendCommandForIrp( |
| pFilter, |
| pIrp, |
| otLwfTunIoCtl_otExtendedAddress_Handler, |
| SPINEL_CMD_PROP_VALUE_GET, |
| SPINEL_PROP_HWADDR, |
| 0, |
| NULL); |
| } |
| |
| return status; |
| } |
| |
| _IRQL_requires_max_(DISPATCH_LEVEL) |
| NTSTATUS |
| otLwfTunIoCtl_otExtendedAddress_Handler( |
| _In_ spinel_prop_key_t Key, |
| _In_reads_bytes_(DataLength) const uint8_t* Data, |
| _In_ spinel_size_t DataLength, |
| _Out_writes_bytes_(*OutBufferLength) |
| PVOID OutBuffer, |
| _Inout_ PULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_INVALID_PARAMETER; |
| if (Key == SPINEL_PROP_HWADDR) |
| { |
| spinel_eui64_t *data = NULL; |
| if (try_spinel_datatype_unpack(Data, DataLength, SPINEL_DATATYPE_EUI64_S, &data) && data != NULL) |
| { |
| memcpy(OutBuffer, data, sizeof(otExtAddress)); |
| *OutBufferLength = sizeof(otExtAddress); |
| status = STATUS_SUCCESS; |
| } |
| } |
| return status; |
| } |
| |
| _IRQL_requires_max_(PASSIVE_LEVEL) |
| NTSTATUS |
| otLwfIoCtl_otExtendedPanId( |
| _In_ PMS_FILTER pFilter, |
| _In_reads_bytes_(InBufferLength) |
| PUCHAR InBuffer, |
| _In_ ULONG InBufferLength, |
| _Out_writes_bytes_(*OutBufferLength) |
| PVOID OutBuffer, |
| _Inout_ PULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_INVALID_PARAMETER; |
| |
| if (InBufferLength >= sizeof(otExtendedPanId)) |
| { |
| status = ThreadErrorToNtstatus(otThreadSetExtendedPanId(pFilter->otCtx, (uint8_t*)InBuffer)); |
| *OutBufferLength = 0; |
| } |
| else if (*OutBufferLength >= sizeof(otExtendedPanId)) |
| { |
| memcpy(OutBuffer, otThreadGetExtendedPanId(pFilter->otCtx), sizeof(otExtendedPanId)); |
| *OutBufferLength = sizeof(otExtendedPanId); |
| status = STATUS_SUCCESS; |
| } |
| else |
| { |
| *OutBufferLength = 0; |
| } |
| |
| return status; |
| } |
| |
| _IRQL_requires_max_(PASSIVE_LEVEL) |
| NTSTATUS |
| otLwfTunIoCtl_otExtendedPanId( |
| _In_ PMS_FILTER pFilter, |
| _In_ PIRP pIrp, |
| _In_reads_bytes_(InBufferLength) |
| PUCHAR InBuffer, |
| _In_ ULONG InBufferLength, |
| _In_ ULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_INVALID_PARAMETER; |
| |
| if (InBufferLength >= sizeof(otExtendedPanId)) |
| { |
| status = |
| otLwfTunSendCommandForIrp( |
| pFilter, |
| pIrp, |
| NULL, |
| SPINEL_CMD_PROP_VALUE_SET, |
| SPINEL_PROP_NET_XPANID, |
| sizeof(otExtendedPanId) + sizeof(uint16_t), |
| SPINEL_DATATYPE_DATA_S, |
| (otExtendedPanId*)InBuffer, |
| sizeof(otExtendedPanId)); |
| } |
| else if (OutBufferLength >= sizeof(otExtendedPanId)) |
| { |
| status = |
| otLwfTunSendCommandForIrp( |
| pFilter, |
| pIrp, |
| otLwfTunIoCtl_otExtendedPanId_Handler, |
| SPINEL_CMD_PROP_VALUE_GET, |
| SPINEL_PROP_NET_XPANID, |
| 0, |
| NULL); |
| } |
| |
| return status; |
| } |
| |
| _IRQL_requires_max_(DISPATCH_LEVEL) |
| NTSTATUS |
| otLwfTunIoCtl_otExtendedPanId_Handler( |
| _In_ spinel_prop_key_t Key, |
| _In_reads_bytes_(DataLength) const uint8_t* Data, |
| _In_ spinel_size_t DataLength, |
| _Out_writes_bytes_(*OutBufferLength) |
| PVOID OutBuffer, |
| _Inout_ PULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_INVALID_PARAMETER; |
| if (Key == SPINEL_PROP_NET_XPANID) |
| { |
| uint8_t *data = NULL; |
| spinel_size_t aExtPanIdLen; |
| if (try_spinel_datatype_unpack(Data, DataLength, SPINEL_DATATYPE_DATA_S, &data, &aExtPanIdLen) && data != NULL && |
| aExtPanIdLen == sizeof(otExtendedPanId)) |
| { |
| memcpy(OutBuffer, data, sizeof(otExtendedPanId)); |
| *OutBufferLength = sizeof(otExtendedPanId); |
| status = STATUS_SUCCESS; |
| } |
| } |
| return status; |
| } |
| |
| _IRQL_requires_max_(PASSIVE_LEVEL) |
| NTSTATUS |
| otLwfIoCtl_otFactoryAssignedIeeeEui64( |
| _In_ PMS_FILTER pFilter, |
| _In_reads_bytes_(InBufferLength) |
| PUCHAR InBuffer, |
| _In_ ULONG InBufferLength, |
| _Out_writes_bytes_(*OutBufferLength) |
| PVOID OutBuffer, |
| _Inout_ PULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_INVALID_PARAMETER; |
| |
| UNREFERENCED_PARAMETER(InBuffer); |
| UNREFERENCED_PARAMETER(InBufferLength); |
| |
| if (*OutBufferLength >= sizeof(otExtAddress)) |
| { |
| otLinkGetFactoryAssignedIeeeEui64(pFilter->otCtx, (otExtAddress*)OutBuffer); |
| *OutBufferLength = sizeof(otExtAddress); |
| status = STATUS_SUCCESS; |
| } |
| else |
| { |
| *OutBufferLength = 0; |
| } |
| |
| return status; |
| } |
| |
| _IRQL_requires_max_(PASSIVE_LEVEL) |
| NTSTATUS |
| otLwfIoCtl_otHashMacAddress( |
| _In_ PMS_FILTER pFilter, |
| _In_reads_bytes_(InBufferLength) |
| PUCHAR InBuffer, |
| _In_ ULONG InBufferLength, |
| _Out_writes_bytes_(*OutBufferLength) |
| PVOID OutBuffer, |
| _Inout_ PULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_INVALID_PARAMETER; |
| |
| UNREFERENCED_PARAMETER(InBuffer); |
| UNREFERENCED_PARAMETER(InBufferLength); |
| |
| if (*OutBufferLength >= sizeof(otExtAddress)) |
| { |
| otLinkGetJoinerId(pFilter->otCtx, (otExtAddress*)OutBuffer); |
| *OutBufferLength = sizeof(otExtAddress); |
| status = STATUS_SUCCESS; |
| } |
| else |
| { |
| *OutBufferLength = 0; |
| } |
| |
| return status; |
| } |
| |
| _IRQL_requires_max_(PASSIVE_LEVEL) |
| NTSTATUS |
| otLwfIoCtl_otLeaderRloc( |
| _In_ PMS_FILTER pFilter, |
| _In_reads_bytes_(InBufferLength) |
| PUCHAR InBuffer, |
| _In_ ULONG InBufferLength, |
| _Out_writes_bytes_(*OutBufferLength) |
| PVOID OutBuffer, |
| _Inout_ PULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_INVALID_PARAMETER; |
| |
| UNREFERENCED_PARAMETER(InBuffer); |
| UNREFERENCED_PARAMETER(InBufferLength); |
| |
| if (*OutBufferLength >= sizeof(otIp6Address)) |
| { |
| status = ThreadErrorToNtstatus(otThreadGetLeaderRloc(pFilter->otCtx, (otIp6Address*)OutBuffer)); |
| *OutBufferLength = sizeof(otIp6Address); |
| } |
| else |
| { |
| *OutBufferLength = 0; |
| } |
| |
| return status; |
| } |
| |
| _IRQL_requires_max_(PASSIVE_LEVEL) |
| NTSTATUS |
| otLwfTunIoCtl_otLeaderRloc( |
| _In_ PMS_FILTER pFilter, |
| _In_ PIRP pIrp, |
| _In_reads_bytes_(InBufferLength) |
| PUCHAR InBuffer, |
| _In_ ULONG InBufferLength, |
| _In_ ULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_INVALID_PARAMETER; |
| |
| if (InBufferLength >= sizeof(otIp6Address)) |
| { |
| status = |
| otLwfTunSendCommandForIrp( |
| pFilter, |
| pIrp, |
| NULL, |
| SPINEL_CMD_PROP_VALUE_SET, |
| SPINEL_PROP_THREAD_LEADER_ADDR, |
| sizeof(otIp6Address), |
| SPINEL_DATATYPE_IPv6ADDR_S, |
| (otIp6Address*)InBuffer); |
| } |
| else if (OutBufferLength >= sizeof(otIp6Address)) |
| { |
| status = |
| otLwfTunSendCommandForIrp( |
| pFilter, |
| pIrp, |
| otLwfTunIoCtl_otLeaderRloc_Handler, |
| SPINEL_CMD_PROP_VALUE_GET, |
| SPINEL_PROP_THREAD_LEADER_ADDR, |
| 0, |
| NULL); |
| } |
| |
| return status; |
| } |
| |
| _IRQL_requires_max_(DISPATCH_LEVEL) |
| NTSTATUS |
| otLwfTunIoCtl_otLeaderRloc_Handler( |
| _In_ spinel_prop_key_t Key, |
| _In_reads_bytes_(DataLength) const uint8_t* Data, |
| _In_ spinel_size_t DataLength, |
| _Out_writes_bytes_(*OutBufferLength) |
| PVOID OutBuffer, |
| _Inout_ PULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_INVALID_PARAMETER; |
| if (Key == SPINEL_PROP_THREAD_LEADER_ADDR) |
| { |
| spinel_ipv6addr_t *data = NULL; |
| if (try_spinel_datatype_unpack(Data, DataLength, SPINEL_DATATYPE_IPv6ADDR_S, &data) && data != NULL) |
| { |
| memcpy(OutBuffer, data, sizeof(spinel_ipv6addr_t)); |
| *OutBufferLength = sizeof(otIp6Address); |
| status = STATUS_SUCCESS; |
| } |
| } |
| return status; |
| } |
| |
| _IRQL_requires_max_(PASSIVE_LEVEL) |
| NTSTATUS |
| otLwfIoCtl_otLinkMode( |
| _In_ PMS_FILTER pFilter, |
| _In_reads_bytes_(InBufferLength) |
| PUCHAR InBuffer, |
| _In_ ULONG InBufferLength, |
| _Out_writes_bytes_(*OutBufferLength) |
| PVOID OutBuffer, |
| _Inout_ PULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_INVALID_PARAMETER; |
| |
| static_assert(sizeof(otLinkModeConfig) == 4, "The size of otLinkModeConfig should be 4 bytes"); |
| if (InBufferLength >= sizeof(otLinkModeConfig)) |
| { |
| status = ThreadErrorToNtstatus(otThreadSetLinkMode(pFilter->otCtx, *(otLinkModeConfig*)InBuffer)); |
| *OutBufferLength = 0; |
| } |
| else if (*OutBufferLength >= sizeof(otLinkModeConfig)) |
| { |
| *(otLinkModeConfig*)OutBuffer = otThreadGetLinkMode(pFilter->otCtx); |
| *OutBufferLength = sizeof(otLinkModeConfig); |
| status = STATUS_SUCCESS; |
| } |
| else |
| { |
| *OutBufferLength = 0; |
| } |
| |
| return status; |
| } |
| |
| enum |
| { |
| kThreadMode_RxOnWhenIdle = (1 << 3), |
| kThreadMode_SecureDataRequest = (1 << 2), |
| kThreadMode_FullFunctionDevice = (1 << 1), |
| kThreadMode_FullNetworkData = (1 << 0), |
| }; |
| |
| _IRQL_requires_max_(PASSIVE_LEVEL) |
| NTSTATUS |
| otLwfTunIoCtl_otLinkMode( |
| _In_ PMS_FILTER pFilter, |
| _In_ PIRP pIrp, |
| _In_reads_bytes_(InBufferLength) |
| PUCHAR InBuffer, |
| _In_ ULONG InBufferLength, |
| _In_ ULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_INVALID_PARAMETER; |
| |
| if (InBufferLength >= sizeof(otLinkModeConfig)) |
| { |
| const otLinkModeConfig* aLinkMode = (otLinkModeConfig*)InBuffer; |
| uint8_t numeric_mode = 0; |
| |
| if (aLinkMode->mRxOnWhenIdle) numeric_mode |= kThreadMode_RxOnWhenIdle; |
| if (aLinkMode->mSecureDataRequests) numeric_mode |= kThreadMode_SecureDataRequest; |
| if (aLinkMode->mDeviceType) numeric_mode |= kThreadMode_FullFunctionDevice; |
| if (aLinkMode->mNetworkData) numeric_mode |= kThreadMode_FullNetworkData; |
| |
| status = |
| otLwfTunSendCommandForIrp( |
| pFilter, |
| pIrp, |
| NULL, |
| SPINEL_CMD_PROP_VALUE_SET, |
| SPINEL_PROP_THREAD_MODE, |
| sizeof(uint8_t), |
| SPINEL_DATATYPE_UINT8_S, |
| numeric_mode); |
| } |
| else if (OutBufferLength >= sizeof(otLinkModeConfig)) |
| { |
| status = |
| otLwfTunSendCommandForIrp( |
| pFilter, |
| pIrp, |
| otLwfTunIoCtl_otLinkMode_Handler, |
| SPINEL_CMD_PROP_VALUE_GET, |
| SPINEL_PROP_THREAD_MODE, |
| 0, |
| NULL); |
| } |
| |
| return status; |
| } |
| |
| _IRQL_requires_max_(DISPATCH_LEVEL) |
| NTSTATUS |
| otLwfTunIoCtl_otLinkMode_Handler( |
| _In_ spinel_prop_key_t Key, |
| _In_reads_bytes_(DataLength) const uint8_t* Data, |
| _In_ spinel_size_t DataLength, |
| _Out_writes_bytes_(*OutBufferLength) |
| PVOID OutBuffer, |
| _Inout_ PULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_INVALID_PARAMETER; |
| if (Key == SPINEL_PROP_THREAD_MODE) |
| { |
| uint8_t numeric_mode = 0; |
| if (try_spinel_datatype_unpack(Data, DataLength, SPINEL_DATATYPE_UINT8_S, &numeric_mode)) |
| { |
| otLinkModeConfig* aLinkMode = (otLinkModeConfig*)OutBuffer; |
| |
| aLinkMode->mRxOnWhenIdle = ((numeric_mode & kThreadMode_RxOnWhenIdle) == kThreadMode_RxOnWhenIdle); |
| aLinkMode->mSecureDataRequests = ((numeric_mode & kThreadMode_SecureDataRequest) == kThreadMode_SecureDataRequest); |
| aLinkMode->mDeviceType = ((numeric_mode & kThreadMode_FullFunctionDevice) == kThreadMode_FullFunctionDevice); |
| aLinkMode->mNetworkData = ((numeric_mode & kThreadMode_FullNetworkData) == kThreadMode_FullNetworkData); |
| |
| *OutBufferLength = sizeof(otLinkModeConfig); |
| status = STATUS_SUCCESS; |
| } |
| } |
| return status; |
| } |
| |
| _IRQL_requires_max_(PASSIVE_LEVEL) |
| NTSTATUS |
| otLwfIoCtl_otMasterKey( |
| _In_ PMS_FILTER pFilter, |
| _In_reads_bytes_(InBufferLength) |
| PUCHAR InBuffer, |
| _In_ ULONG InBufferLength, |
| _Out_writes_bytes_(*OutBufferLength) |
| PVOID OutBuffer, |
| _Inout_ PULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_INVALID_PARAMETER; |
| |
| if (InBufferLength >= sizeof(otMasterKey)) |
| { |
| status = ThreadErrorToNtstatus(otThreadSetMasterKey(pFilter->otCtx, (otMasterKey*)InBuffer)); |
| *OutBufferLength = 0; |
| } |
| else if (*OutBufferLength >= sizeof(otMasterKey)) |
| { |
| const otMasterKey* aMasterKey = otThreadGetMasterKey(pFilter->otCtx); |
| memcpy(OutBuffer, aMasterKey, sizeof(otMasterKey)); |
| *OutBufferLength = sizeof(otMasterKey); |
| status = STATUS_SUCCESS; |
| } |
| else |
| { |
| *OutBufferLength = 0; |
| } |
| |
| return status; |
| } |
| |
| _IRQL_requires_max_(PASSIVE_LEVEL) |
| NTSTATUS |
| otLwfTunIoCtl_otMasterKey( |
| _In_ PMS_FILTER pFilter, |
| _In_ PIRP pIrp, |
| _In_reads_bytes_(InBufferLength) |
| PUCHAR InBuffer, |
| _In_ ULONG InBufferLength, |
| _In_ ULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_INVALID_PARAMETER; |
| |
| if (InBufferLength >= sizeof(otMasterKey)) |
| { |
| status = |
| otLwfTunSendCommandForIrp( |
| pFilter, |
| pIrp, |
| NULL, |
| SPINEL_CMD_PROP_VALUE_SET, |
| SPINEL_PROP_NET_MASTER_KEY, |
| sizeof(otMasterKey) + sizeof(uint16_t), |
| SPINEL_DATATYPE_DATA_S, |
| (otMasterKey*)InBuffer, |
| sizeof(otMasterKey)); |
| } |
| else if (OutBufferLength >= sizeof(otMasterKey)) |
| { |
| status = |
| otLwfTunSendCommandForIrp( |
| pFilter, |
| pIrp, |
| otLwfTunIoCtl_otMasterKey_Handler, |
| SPINEL_CMD_PROP_VALUE_GET, |
| SPINEL_PROP_NET_MASTER_KEY, |
| 0, |
| NULL); |
| } |
| |
| return status; |
| } |
| |
| _IRQL_requires_max_(DISPATCH_LEVEL) |
| NTSTATUS |
| otLwfTunIoCtl_otMasterKey_Handler( |
| _In_ spinel_prop_key_t Key, |
| _In_reads_bytes_(DataLength) const uint8_t* Data, |
| _In_ spinel_size_t DataLength, |
| _Out_writes_bytes_(*OutBufferLength) |
| PVOID OutBuffer, |
| _Inout_ PULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_INVALID_PARAMETER; |
| if (Key == SPINEL_PROP_NET_MASTER_KEY) |
| { |
| uint8_t *data = NULL; |
| spinel_size_t aKeyLength; |
| if (try_spinel_datatype_unpack(Data, DataLength, SPINEL_DATATYPE_DATA_S, &data, &aKeyLength) && data != NULL && |
| aKeyLength == sizeof(otMasterKey)) |
| { |
| memcpy(OutBuffer, data, sizeof(otMasterKey)); |
| *OutBufferLength = sizeof(otMasterKey); |
| status = STATUS_SUCCESS; |
| } |
| } |
| return status; |
| } |
| |
| _IRQL_requires_max_(PASSIVE_LEVEL) |
| NTSTATUS |
| otLwfIoCtl_otPSKc( |
| _In_ PMS_FILTER pFilter, |
| _In_reads_bytes_(InBufferLength) |
| PUCHAR InBuffer, |
| _In_ ULONG InBufferLength, |
| _Out_writes_bytes_(*OutBufferLength) |
| PVOID OutBuffer, |
| _Inout_ PULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_INVALID_PARAMETER; |
| |
| if (InBufferLength >= sizeof(otPSKc)) |
| { |
| status = ThreadErrorToNtstatus(otThreadSetPSKc(pFilter->otCtx, InBuffer)); |
| *OutBufferLength = 0; |
| } |
| else if (*OutBufferLength >= sizeof(otPSKc)) |
| { |
| const uint8_t* aPSKc = otThreadGetPSKc(pFilter->otCtx); |
| memcpy(OutBuffer, aPSKc, sizeof(otPSKc)); |
| *OutBufferLength = sizeof(otPSKc); |
| status = STATUS_SUCCESS; |
| } |
| else |
| { |
| *OutBufferLength = 0; |
| } |
| |
| return status; |
| } |
| |
| _IRQL_requires_max_(PASSIVE_LEVEL) |
| NTSTATUS |
| otLwfTunIoCtl_otPSKc( |
| _In_ PMS_FILTER pFilter, |
| _In_ PIRP pIrp, |
| _In_reads_bytes_(InBufferLength) |
| PUCHAR InBuffer, |
| _In_ ULONG InBufferLength, |
| _In_ ULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_INVALID_PARAMETER; |
| |
| if (InBufferLength >= sizeof(otPSKc)) |
| { |
| status = |
| otLwfTunSendCommandForIrp( |
| pFilter, |
| pIrp, |
| NULL, |
| SPINEL_CMD_PROP_VALUE_SET, |
| SPINEL_PROP_NET_PSKC, |
| sizeof(otPSKc) + sizeof(uint16_t), |
| SPINEL_DATATYPE_DATA_S, |
| (otPSKc*)InBuffer, |
| OT_PSKC_MAX_SIZE); |
| } |
| else if (OutBufferLength >= sizeof(otPSKc)) |
| { |
| status = |
| otLwfTunSendCommandForIrp( |
| pFilter, |
| pIrp, |
| otLwfTunIoCtl_otPSKc_Handler, |
| SPINEL_CMD_PROP_VALUE_GET, |
| SPINEL_PROP_NET_PSKC, |
| 0, |
| NULL); |
| } |
| |
| return status; |
| } |
| |
| _IRQL_requires_max_(DISPATCH_LEVEL) |
| NTSTATUS |
| otLwfTunIoCtl_otPSKc_Handler( |
| _In_ spinel_prop_key_t Key, |
| _In_reads_bytes_(DataLength) const uint8_t* Data, |
| _In_ spinel_size_t DataLength, |
| _Out_writes_bytes_(*OutBufferLength) |
| PVOID OutBuffer, |
| _Inout_ PULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_INVALID_PARAMETER; |
| if (Key == SPINEL_PROP_NET_PSKC) |
| { |
| uint8_t *data = NULL; |
| spinel_size_t aPSKcLength; |
| if (try_spinel_datatype_unpack(Data, DataLength, SPINEL_DATATYPE_DATA_S, &data, &aPSKcLength) && data != NULL && |
| aPSKcLength == sizeof(otPSKc)) |
| { |
| memcpy(OutBuffer, data, sizeof(otPSKc)); |
| *OutBufferLength = sizeof(otPSKc); |
| status = STATUS_SUCCESS; |
| } |
| } |
| return status; |
| } |
| |
| _IRQL_requires_max_(PASSIVE_LEVEL) |
| NTSTATUS |
| otLwfIoCtl_otMeshLocalEid( |
| _In_ PMS_FILTER pFilter, |
| _In_reads_bytes_(InBufferLength) |
| PUCHAR InBuffer, |
| _In_ ULONG InBufferLength, |
| _Out_writes_bytes_(*OutBufferLength) |
| PVOID OutBuffer, |
| _Inout_ PULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_INVALID_PARAMETER; |
| |
| UNREFERENCED_PARAMETER(InBuffer); |
| UNREFERENCED_PARAMETER(InBufferLength); |
| |
| if (*OutBufferLength >= sizeof(otIp6Address)) |
| { |
| memcpy(OutBuffer, otThreadGetMeshLocalEid(pFilter->otCtx), sizeof(otIp6Address)); |
| status = STATUS_SUCCESS; |
| } |
| else |
| { |
| *OutBufferLength = 0; |
| } |
| |
| return status; |
| } |
| |
| _IRQL_requires_max_(PASSIVE_LEVEL) |
| NTSTATUS |
| otLwfTunIoCtl_otMeshLocalEid( |
| _In_ PMS_FILTER pFilter, |
| _In_ PIRP pIrp, |
| _In_reads_bytes_(InBufferLength) |
| PUCHAR InBuffer, |
| _In_ ULONG InBufferLength, |
| _In_ ULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_INVALID_PARAMETER; |
| |
| UNREFERENCED_PARAMETER(InBuffer); |
| UNREFERENCED_PARAMETER(InBufferLength); |
| |
| if (OutBufferLength >= sizeof(otIp6Address)) |
| { |
| status = |
| otLwfTunSendCommandForIrp( |
| pFilter, |
| pIrp, |
| otLwfTunIoCtl_otMeshLocalEid_Handler, |
| SPINEL_CMD_PROP_VALUE_GET, |
| SPINEL_PROP_IPV6_ML_ADDR, |
| 0, |
| NULL); |
| } |
| |
| return status; |
| } |
| |
| _IRQL_requires_max_(DISPATCH_LEVEL) |
| NTSTATUS |
| otLwfTunIoCtl_otMeshLocalEid_Handler( |
| _In_ spinel_prop_key_t Key, |
| _In_reads_bytes_(DataLength) const uint8_t* Data, |
| _In_ spinel_size_t DataLength, |
| _Out_writes_bytes_(*OutBufferLength) |
| PVOID OutBuffer, |
| _Inout_ PULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_INVALID_PARAMETER; |
| if (Key == SPINEL_PROP_IPV6_ML_ADDR) |
| { |
| spinel_ipv6addr_t *data = NULL; |
| if (try_spinel_datatype_unpack(Data, DataLength, SPINEL_DATATYPE_IPv6ADDR_S, &data) && data != NULL) |
| { |
| memcpy(OutBuffer, data, sizeof(spinel_ipv6addr_t)); |
| *OutBufferLength = sizeof(otIp6Address); |
| status = STATUS_SUCCESS; |
| } |
| } |
| return status; |
| } |
| |
| _IRQL_requires_max_(PASSIVE_LEVEL) |
| NTSTATUS |
| otLwfIoCtl_otMeshLocalPrefix( |
| _In_ PMS_FILTER pFilter, |
| _In_reads_bytes_(InBufferLength) |
| PUCHAR InBuffer, |
| _In_ ULONG InBufferLength, |
| _Out_writes_bytes_(*OutBufferLength) |
| PVOID OutBuffer, |
| _Inout_ PULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_INVALID_PARAMETER; |
| |
| if (InBufferLength >= sizeof(otMeshLocalPrefix)) |
| { |
| status = ThreadErrorToNtstatus(otThreadSetMeshLocalPrefix(pFilter->otCtx, InBuffer)); |
| *OutBufferLength = 0; |
| } |
| else if (*OutBufferLength >= sizeof(otMeshLocalPrefix)) |
| { |
| memcpy(OutBuffer, otThreadGetMeshLocalPrefix(pFilter->otCtx), sizeof(otMeshLocalPrefix)); |
| *OutBufferLength = sizeof(otMeshLocalPrefix); |
| status = STATUS_SUCCESS; |
| } |
| else |
| { |
| *OutBufferLength = 0; |
| } |
| |
| return status; |
| } |
| |
| _IRQL_requires_max_(PASSIVE_LEVEL) |
| NTSTATUS |
| otLwfTunIoCtl_otMeshLocalPrefix( |
| _In_ PMS_FILTER pFilter, |
| _In_ PIRP pIrp, |
| _In_reads_bytes_(InBufferLength) |
| PUCHAR InBuffer, |
| _In_ ULONG InBufferLength, |
| _In_ ULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_INVALID_PARAMETER; |
| |
| if (InBufferLength >= sizeof(otMeshLocalPrefix)) |
| { |
| otIp6Address aAddress = {0}; |
| memcpy(&aAddress, InBuffer, sizeof(otMeshLocalPrefix)); |
| |
| status = |
| otLwfTunSendCommandForIrp( |
| pFilter, |
| pIrp, |
| NULL, |
| SPINEL_CMD_PROP_VALUE_SET, |
| SPINEL_PROP_IPV6_ML_PREFIX, |
| sizeof(otIp6Address), |
| SPINEL_DATATYPE_IPv6ADDR_S, |
| &aAddress); |
| } |
| else if (OutBufferLength >= sizeof(otMeshLocalPrefix)) |
| { |
| status = |
| otLwfTunSendCommandForIrp( |
| pFilter, |
| pIrp, |
| otLwfTunIoCtl_otMeshLocalPrefix_Handler, |
| SPINEL_CMD_PROP_VALUE_GET, |
| SPINEL_PROP_IPV6_ML_PREFIX, |
| 0, |
| NULL); |
| } |
| |
| return status; |
| } |
| |
| _IRQL_requires_max_(DISPATCH_LEVEL) |
| NTSTATUS |
| otLwfTunIoCtl_otMeshLocalPrefix_Handler( |
| _In_ spinel_prop_key_t Key, |
| _In_reads_bytes_(DataLength) const uint8_t* Data, |
| _In_ spinel_size_t DataLength, |
| _Out_writes_bytes_(*OutBufferLength) |
| PVOID OutBuffer, |
| _Inout_ PULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_INVALID_PARAMETER; |
| if (Key == SPINEL_PROP_IPV6_ML_PREFIX) |
| { |
| if (DataLength >= sizeof(otMeshLocalPrefix)) |
| { |
| memcpy(OutBuffer, Data, sizeof(otMeshLocalPrefix)); |
| *OutBufferLength = sizeof(otMeshLocalPrefix); |
| status = STATUS_SUCCESS; |
| } |
| } |
| return status; |
| } |
| |
| // otLwfIoCtl_otNetworkDataLeader |
| |
| // otLwfIoCtl_otNetworkDataLocal |
| |
| _IRQL_requires_max_(PASSIVE_LEVEL) |
| NTSTATUS |
| otLwfIoCtl_otNetworkName( |
| _In_ PMS_FILTER pFilter, |
| _In_reads_bytes_(InBufferLength) |
| PUCHAR InBuffer, |
| _In_ ULONG InBufferLength, |
| _Out_writes_bytes_(*OutBufferLength) |
| PVOID OutBuffer, |
| _Inout_ PULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_INVALID_PARAMETER; |
| |
| if (InBufferLength >= sizeof(otNetworkName)) |
| { |
| status = ThreadErrorToNtstatus(otThreadSetNetworkName(pFilter->otCtx, (char*)InBuffer)); |
| *OutBufferLength = 0; |
| } |
| else if (*OutBufferLength >= sizeof(otNetworkName)) |
| { |
| strcpy_s((char*)OutBuffer, sizeof(otNetworkName), otThreadGetNetworkName(pFilter->otCtx)); |
| *OutBufferLength = sizeof(otNetworkName); |
| status = STATUS_SUCCESS; |
| } |
| else |
| { |
| *OutBufferLength = 0; |
| } |
| |
| return status; |
| } |
| |
| _IRQL_requires_max_(PASSIVE_LEVEL) |
| NTSTATUS |
| otLwfTunIoCtl_otNetworkName( |
| _In_ PMS_FILTER pFilter, |
| _In_ PIRP pIrp, |
| _In_reads_bytes_(InBufferLength) |
| PUCHAR InBuffer, |
| _In_ ULONG InBufferLength, |
| _In_ ULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_INVALID_PARAMETER; |
| |
| if (InBufferLength >= sizeof(otNetworkName)) |
| { |
| status = |
| otLwfTunSendCommandForIrp( |
| pFilter, |
| pIrp, |
| NULL, |
| SPINEL_CMD_PROP_VALUE_SET, |
| SPINEL_PROP_NET_NETWORK_NAME, |
| sizeof(otIp6Address), |
| SPINEL_DATATYPE_UTF8_S, |
| (otNetworkName*)InBuffer); |
| } |
| else if (OutBufferLength >= sizeof(otNetworkName)) |
| { |
| status = |
| otLwfTunSendCommandForIrp( |
| pFilter, |
| pIrp, |
| otLwfTunIoCtl_otNetworkName_Handler, |
| SPINEL_CMD_PROP_VALUE_GET, |
| SPINEL_PROP_NET_NETWORK_NAME, |
| 0, |
| NULL); |
| } |
| |
| return status; |
| } |
| |
| _IRQL_requires_max_(DISPATCH_LEVEL) |
| NTSTATUS |
| otLwfTunIoCtl_otNetworkName_Handler( |
| _In_ spinel_prop_key_t Key, |
| _In_reads_bytes_(DataLength) const uint8_t* Data, |
| _In_ spinel_size_t DataLength, |
| _Out_writes_bytes_(*OutBufferLength) |
| PVOID OutBuffer, |
| _Inout_ PULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_INVALID_PARAMETER; |
| if (Key == SPINEL_PROP_NET_NETWORK_NAME) |
| { |
| const char *data = NULL; |
| if (try_spinel_datatype_unpack(Data, DataLength, SPINEL_DATATYPE_UTF8_S, &data) && data != NULL) |
| { |
| strcpy_s(OutBuffer, sizeof(otNetworkName), data); |
| *OutBufferLength = sizeof(otNetworkName); |
| status = STATUS_SUCCESS; |
| } |
| } |
| return status; |
| } |
| |
| _IRQL_requires_max_(PASSIVE_LEVEL) |
| NTSTATUS |
| otLwfIoCtl_otPanId( |
| _In_ PMS_FILTER pFilter, |
| _In_reads_bytes_(InBufferLength) |
| PUCHAR InBuffer, |
| _In_ ULONG InBufferLength, |
| _Out_writes_bytes_(*OutBufferLength) |
| PVOID OutBuffer, |
| _Inout_ PULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_INVALID_PARAMETER; |
| |
| if (InBufferLength >= sizeof(otPanId)) |
| { |
| status = ThreadErrorToNtstatus(otLinkSetPanId(pFilter->otCtx, *(otPanId*)InBuffer)); |
| *OutBufferLength = 0; |
| } |
| else if (*OutBufferLength >= sizeof(otPanId)) |
| { |
| *(otPanId*)OutBuffer = otLinkGetPanId(pFilter->otCtx); |
| *OutBufferLength = sizeof(otPanId); |
| status = STATUS_SUCCESS; |
| } |
| else |
| { |
| *OutBufferLength = 0; |
| } |
| |
| return status; |
| } |
| |
| _IRQL_requires_max_(PASSIVE_LEVEL) |
| NTSTATUS |
| otLwfTunIoCtl_otPanId( |
| _In_ PMS_FILTER pFilter, |
| _In_ PIRP pIrp, |
| _In_reads_bytes_(InBufferLength) |
| PUCHAR InBuffer, |
| _In_ ULONG InBufferLength, |
| _In_ ULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_INVALID_PARAMETER; |
| |
| if (InBufferLength >= sizeof(otPanId)) |
| { |
| status = |
| otLwfTunSendCommandForIrp( |
| pFilter, |
| pIrp, |
| NULL, |
| SPINEL_CMD_PROP_VALUE_SET, |
| SPINEL_PROP_MAC_15_4_PANID, |
| sizeof(otPanId), |
| SPINEL_DATATYPE_UINT16_S, |
| *(otPanId*)InBuffer); |
| } |
| else if (OutBufferLength >= sizeof(otPanId)) |
| { |
| status = |
| otLwfTunSendCommandForIrp( |
| pFilter, |
| pIrp, |
| otLwfTunIoCtl_otPanId_Handler, |
| SPINEL_CMD_PROP_VALUE_GET, |
| SPINEL_PROP_MAC_15_4_PANID, |
| 0, |
| NULL); |
| } |
| |
| return status; |
| } |
| |
| _IRQL_requires_max_(DISPATCH_LEVEL) |
| NTSTATUS |
| otLwfTunIoCtl_otPanId_Handler( |
| _In_ spinel_prop_key_t Key, |
| _In_reads_bytes_(DataLength) const uint8_t* Data, |
| _In_ spinel_size_t DataLength, |
| _Out_writes_bytes_(*OutBufferLength) |
| PVOID OutBuffer, |
| _Inout_ PULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_INVALID_PARAMETER; |
| if (Key == SPINEL_PROP_MAC_15_4_PANID) |
| { |
| if (try_spinel_datatype_unpack(Data, DataLength, SPINEL_DATATYPE_UINT16_S, (otPanId*)OutBuffer)) |
| { |
| *OutBufferLength = sizeof(otPanId); |
| status = STATUS_SUCCESS; |
| } |
| } |
| return status; |
| } |
| |
| _IRQL_requires_max_(PASSIVE_LEVEL) |
| NTSTATUS |
| otLwfIoCtl_otRouterRollEnabled( |
| _In_ PMS_FILTER pFilter, |
| _In_reads_bytes_(InBufferLength) |
| PUCHAR InBuffer, |
| _In_ ULONG InBufferLength, |
| _Out_writes_bytes_(*OutBufferLength) |
| PVOID OutBuffer, |
| _Inout_ PULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_INVALID_PARAMETER; |
| |
| if (InBufferLength >= sizeof(BOOLEAN)) |
| { |
| otThreadSetRouterRoleEnabled(pFilter->otCtx, *(BOOLEAN*)InBuffer); |
| status = STATUS_SUCCESS; |
| *OutBufferLength = 0; |
| } |
| else if (*OutBufferLength >= sizeof(BOOLEAN)) |
| { |
| *(BOOLEAN*)OutBuffer = otThreadIsRouterRoleEnabled(pFilter->otCtx) ? TRUE : FALSE; |
| *OutBufferLength = sizeof(BOOLEAN); |
| status = STATUS_SUCCESS; |
| } |
| else |
| { |
| *OutBufferLength = 0; |
| } |
| |
| return status; |
| } |
| |
| _IRQL_requires_max_(PASSIVE_LEVEL) |
| NTSTATUS |
| otLwfTunIoCtl_otRouterRollEnabled( |
| _In_ PMS_FILTER pFilter, |
| _In_ PIRP pIrp, |
| _In_reads_bytes_(InBufferLength) |
| PUCHAR InBuffer, |
| _In_ ULONG InBufferLength, |
| _In_ ULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_INVALID_PARAMETER; |
| |
| if (InBufferLength >= sizeof(BOOLEAN)) |
| { |
| status = |
| otLwfTunSendCommandForIrp( |
| pFilter, |
| pIrp, |
| NULL, |
| SPINEL_CMD_PROP_VALUE_SET, |
| SPINEL_PROP_THREAD_ROUTER_ROLE_ENABLED, |
| sizeof(BOOLEAN), |
| SPINEL_DATATYPE_BOOL_S, |
| *(BOOLEAN*)InBuffer); |
| } |
| else if (OutBufferLength >= sizeof(BOOLEAN)) |
| { |
| status = |
| otLwfTunSendCommandForIrp( |
| pFilter, |
| pIrp, |
| otLwfTunIoCtl_otRouterRollEnabled_Handler, |
| SPINEL_CMD_PROP_VALUE_GET, |
| SPINEL_PROP_THREAD_ROUTER_ROLE_ENABLED, |
| 0, |
| NULL); |
| } |
| |
| return status; |
| } |
| |
| _IRQL_requires_max_(DISPATCH_LEVEL) |
| NTSTATUS |
| otLwfTunIoCtl_otRouterRollEnabled_Handler( |
| _In_ spinel_prop_key_t Key, |
| _In_reads_bytes_(DataLength) const uint8_t* Data, |
| _In_ spinel_size_t DataLength, |
| _Out_writes_bytes_(*OutBufferLength) |
| PVOID OutBuffer, |
| _Inout_ PULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_INVALID_PARAMETER; |
| if (Key == SPINEL_PROP_THREAD_ROUTER_ROLE_ENABLED) |
| { |
| if (try_spinel_datatype_unpack(Data, DataLength, SPINEL_DATATYPE_BOOL_S, (BOOLEAN*)OutBuffer)) |
| { |
| *OutBufferLength = sizeof(BOOLEAN); |
| status = STATUS_SUCCESS; |
| } |
| } |
| return status; |
| } |
| |
| _IRQL_requires_max_(PASSIVE_LEVEL) |
| NTSTATUS |
| otLwfIoCtl_otShortAddress( |
| _In_ PMS_FILTER pFilter, |
| _In_reads_bytes_(InBufferLength) |
| PUCHAR InBuffer, |
| _In_ ULONG InBufferLength, |
| _Out_writes_bytes_(*OutBufferLength) |
| PVOID OutBuffer, |
| _Inout_ PULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_INVALID_PARAMETER; |
| |
| UNREFERENCED_PARAMETER(InBuffer); |
| UNREFERENCED_PARAMETER(InBufferLength); |
| |
| if (*OutBufferLength >= sizeof(otShortAddress)) |
| { |
| *(otShortAddress*)OutBuffer = otLinkGetShortAddress(pFilter->otCtx); |
| *OutBufferLength = sizeof(otShortAddress); |
| status = STATUS_SUCCESS; |
| } |
| else |
| { |
| *OutBufferLength = 0; |
| } |
| |
| return status; |
| } |
| |
| _IRQL_requires_max_(PASSIVE_LEVEL) |
| NTSTATUS |
| otLwfTunIoCtl_otShortAddress( |
| _In_ PMS_FILTER pFilter, |
| _In_ PIRP pIrp, |
| _In_reads_bytes_(InBufferLength) |
| PUCHAR InBuffer, |
| _In_ ULONG InBufferLength, |
| _In_ ULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_INVALID_PARAMETER; |
| |
| UNREFERENCED_PARAMETER(InBuffer); |
| UNREFERENCED_PARAMETER(InBufferLength); |
| |
| if (OutBufferLength >= sizeof(otShortAddress)) |
| { |
| status = |
| otLwfTunSendCommandForIrp( |
| pFilter, |
| pIrp, |
| otLwfTunIoCtl_otShortAddress_Handler, |
| SPINEL_CMD_PROP_VALUE_GET, |
| SPINEL_PROP_MAC_15_4_SADDR, |
| 0, |
| NULL); |
| } |
| |
| return status; |
| } |
| |
| _IRQL_requires_max_(DISPATCH_LEVEL) |
| NTSTATUS |
| otLwfTunIoCtl_otShortAddress_Handler( |
| _In_ spinel_prop_key_t Key, |
| _In_reads_bytes_(DataLength) const uint8_t* Data, |
| _In_ spinel_size_t DataLength, |
| _Out_writes_bytes_(*OutBufferLength) |
| PVOID OutBuffer, |
| _Inout_ PULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_INVALID_PARAMETER; |
| if (Key == SPINEL_PROP_MAC_15_4_SADDR) |
| { |
| if (try_spinel_datatype_unpack(Data, DataLength, SPINEL_DATATYPE_UINT16_S, (otShortAddress*)OutBuffer)) |
| { |
| *OutBufferLength = sizeof(otShortAddress); |
| status = STATUS_SUCCESS; |
| } |
| } |
| return status; |
| } |
| |
| // otLwfIoCtl_otUnicastAddresses |
| |
| _IRQL_requires_max_(PASSIVE_LEVEL) |
| NTSTATUS |
| otLwfIoCtl_otActiveDataset( |
| _In_ PMS_FILTER pFilter, |
| _In_reads_bytes_(InBufferLength) |
| PUCHAR InBuffer, |
| _In_ ULONG InBufferLength, |
| _Out_writes_bytes_(*OutBufferLength) |
| PVOID OutBuffer, |
| _Inout_ PULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_INVALID_PARAMETER; |
| |
| if (InBufferLength >= sizeof(otOperationalDataset)) |
| { |
| status = ThreadErrorToNtstatus(otDatasetSetActive(pFilter->otCtx, (otOperationalDataset*)InBuffer)); |
| *OutBufferLength = 0; |
| } |
| else if (*OutBufferLength >= sizeof(otOperationalDataset)) |
| { |
| status = ThreadErrorToNtstatus(otDatasetGetActive(pFilter->otCtx, (otOperationalDataset*)OutBuffer)); |
| *OutBufferLength = sizeof(otOperationalDataset); |
| } |
| else |
| { |
| *OutBufferLength = 0; |
| } |
| |
| return status; |
| } |
| |
| _IRQL_requires_max_(PASSIVE_LEVEL) |
| NTSTATUS |
| otLwfIoCtl_otPendingDataset( |
| _In_ PMS_FILTER pFilter, |
| _In_reads_bytes_(InBufferLength) |
| PUCHAR InBuffer, |
| _In_ ULONG InBufferLength, |
| _Out_writes_bytes_(*OutBufferLength) |
| PVOID OutBuffer, |
| _Inout_ PULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_INVALID_PARAMETER; |
| |
| if (InBufferLength >= sizeof(otOperationalDataset)) |
| { |
| status = ThreadErrorToNtstatus(otDatasetSetPending(pFilter->otCtx, (otOperationalDataset*)InBuffer)); |
| *OutBufferLength = 0; |
| } |
| else if (*OutBufferLength >= sizeof(otOperationalDataset)) |
| { |
| status = ThreadErrorToNtstatus(otDatasetGetPending(pFilter->otCtx, (otOperationalDataset*)OutBuffer)); |
| *OutBufferLength = sizeof(otOperationalDataset); |
| } |
| else |
| { |
| *OutBufferLength = 0; |
| } |
| |
| return status; |
| } |
| |
| _IRQL_requires_max_(PASSIVE_LEVEL) |
| NTSTATUS |
| otLwfIoCtl_otLocalLeaderWeight( |
| _In_ PMS_FILTER pFilter, |
| _In_reads_bytes_(InBufferLength) |
| PUCHAR InBuffer, |
| _In_ ULONG InBufferLength, |
| _Out_writes_bytes_(*OutBufferLength) |
| PVOID OutBuffer, |
| _Inout_ PULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_INVALID_PARAMETER; |
| |
| if (InBufferLength >= sizeof(uint8_t)) |
| { |
| otThreadSetLocalLeaderWeight(pFilter->otCtx, *(uint8_t*)InBuffer); |
| status = STATUS_SUCCESS; |
| *OutBufferLength = 0; |
| } |
| else if (*OutBufferLength >= sizeof(uint8_t)) |
| { |
| *(uint8_t*)OutBuffer = otThreadGetLeaderWeight(pFilter->otCtx); |
| *OutBufferLength = sizeof(uint8_t); |
| status = STATUS_SUCCESS; |
| } |
| else |
| { |
| *OutBufferLength = 0; |
| } |
| |
| return status; |
| } |
| |
| _IRQL_requires_max_(PASSIVE_LEVEL) |
| NTSTATUS |
| otLwfTunIoCtl_otLocalLeaderWeight( |
| _In_ PMS_FILTER pFilter, |
| _In_ PIRP pIrp, |
| _In_reads_bytes_(InBufferLength) |
| PUCHAR InBuffer, |
| _In_ ULONG InBufferLength, |
| _In_ ULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_INVALID_PARAMETER; |
| |
| if (InBufferLength >= sizeof(uint8_t)) |
| { |
| status = |
| otLwfTunSendCommandForIrp( |
| pFilter, |
| pIrp, |
| NULL, |
| SPINEL_CMD_PROP_VALUE_SET, |
| SPINEL_PROP_THREAD_LOCAL_LEADER_WEIGHT, |
| sizeof(uint8_t), |
| SPINEL_DATATYPE_UINT8_S, |
| *(uint8_t*)InBuffer); |
| } |
| else if (OutBufferLength >= sizeof(uint8_t)) |
| { |
| status = |
| otLwfTunSendCommandForIrp( |
| pFilter, |
| pIrp, |
| otLwfTunIoCtl_otLocalLeaderWeight_Handler, |
| SPINEL_CMD_PROP_VALUE_GET, |
| SPINEL_PROP_THREAD_LOCAL_LEADER_WEIGHT, |
| 0, |
| NULL); |
| } |
| |
| return status; |
| } |
| |
| _IRQL_requires_max_(DISPATCH_LEVEL) |
| NTSTATUS |
| otLwfTunIoCtl_otLocalLeaderWeight_Handler( |
| _In_ spinel_prop_key_t Key, |
| _In_reads_bytes_(DataLength) const uint8_t* Data, |
| _In_ spinel_size_t DataLength, |
| _Out_writes_bytes_(*OutBufferLength) |
| PVOID OutBuffer, |
| _Inout_ PULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_INVALID_PARAMETER; |
| if (Key == SPINEL_PROP_THREAD_LOCAL_LEADER_WEIGHT) |
| { |
| if (try_spinel_datatype_unpack(Data, DataLength, SPINEL_DATATYPE_UINT8_S, (uint8_t*)OutBuffer)) |
| { |
| *OutBufferLength = sizeof(uint8_t); |
| status = STATUS_SUCCESS; |
| } |
| } |
| return status; |
| } |
| |
| _IRQL_requires_max_(PASSIVE_LEVEL) |
| NTSTATUS |
| otLwfIoCtl_otAddBorderRouter( |
| _In_ PMS_FILTER pFilter, |
| _In_reads_bytes_(InBufferLength) |
| PUCHAR InBuffer, |
| _In_ ULONG InBufferLength, |
| _Out_writes_bytes_(*OutBufferLength) |
| PVOID OutBuffer, |
| _Inout_ PULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_INVALID_PARAMETER; |
| |
| UNREFERENCED_PARAMETER(OutBuffer); |
| *OutBufferLength = 0; |
| |
| if (InBufferLength >= sizeof(otBorderRouterConfig)) |
| { |
| status = ThreadErrorToNtstatus(otBorderRouterAddOnMeshPrefix(pFilter->otCtx, (otBorderRouterConfig*)InBuffer)); |
| } |
| |
| return status; |
| } |
| |
| const uint8_t kPreferenceOffset = 6; |
| //const uint8_t kPreferenceMask = 3 << kPreferenceOffset; |
| const uint8_t kPreferredFlag = 1 << 5; |
| const uint8_t kSlaacFlag = 1 << 4; |
| const uint8_t kDhcpFlag = 1 << 3; |
| const uint8_t kConfigureFlag = 1 << 2; |
| const uint8_t kDefaultRouteFlag = 1 << 1; |
| const uint8_t kOnMeshFlag = 1 << 0; |
| |
| _IRQL_requires_max_(PASSIVE_LEVEL) |
| NTSTATUS |
| otLwfTunIoCtl_otAddBorderRouter( |
| _In_ PMS_FILTER pFilter, |
| _In_ PIRP pIrp, |
| _In_reads_bytes_(InBufferLength) |
| PUCHAR InBuffer, |
| _In_ ULONG InBufferLength, |
| _In_ ULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_INVALID_PARAMETER; |
| |
| UNREFERENCED_PARAMETER(OutBufferLength); |
| |
| if (InBufferLength >= sizeof(otBorderRouterConfig)) |
| { |
| const otBorderRouterConfig *aConfig = (otBorderRouterConfig*)InBuffer; |
| |
| otIp6Address prefix = {0}; |
| memcpy_s(&prefix, sizeof(prefix), &aConfig->mPrefix.mPrefix, aConfig->mPrefix.mLength); |
| |
| uint8_t flags = (uint8_t)(aConfig->mPreference << kPreferenceOffset); |
| if (aConfig->mSlaac) flags |= kSlaacFlag; |
| if (aConfig->mDhcp) flags |= kDhcpFlag; |
| if (aConfig->mConfigure) flags |= kConfigureFlag; |
| if (aConfig->mDefaultRoute) flags |= kDefaultRouteFlag; |
| if (aConfig->mOnMesh) flags |= kOnMeshFlag; |
| |
| status = |
| otLwfTunSendCommandForIrp( |
| pFilter, |
| pIrp, |
| NULL, |
| SPINEL_CMD_PROP_VALUE_INSERT, |
| SPINEL_PROP_THREAD_ON_MESH_NETS, |
| sizeof(otIp6Address) + 3 * sizeof(uint8_t), |
| "6CbC", |
| &prefix, |
| aConfig->mPrefix.mLength, |
| aConfig->mStable, |
| flags); |
| } |
| |
| return status; |
| } |
| |
| _IRQL_requires_max_(PASSIVE_LEVEL) |
| NTSTATUS |
| otLwfIoCtl_otRemoveBorderRouter( |
| _In_ PMS_FILTER pFilter, |
| _In_reads_bytes_(InBufferLength) |
| PUCHAR InBuffer, |
| _In_ ULONG InBufferLength, |
| _Out_writes_bytes_(*OutBufferLength) |
| PVOID OutBuffer, |
| _Inout_ PULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_INVALID_PARAMETER; |
| |
| UNREFERENCED_PARAMETER(OutBuffer); |
| *OutBufferLength = 0; |
| |
| if (InBufferLength >= sizeof(otIp6Prefix)) |
| { |
| status = ThreadErrorToNtstatus(otBorderRouterRemoveOnMeshPrefix(pFilter->otCtx, (otIp6Prefix*)InBuffer)); |
| } |
| |
| return status; |
| } |
| |
| _IRQL_requires_max_(PASSIVE_LEVEL) |
| NTSTATUS |
| otLwfTunIoCtl_otRemoveBorderRouter( |
| _In_ PMS_FILTER pFilter, |
| _In_ PIRP pIrp, |
| _In_reads_bytes_(InBufferLength) |
| PUCHAR InBuffer, |
| _In_ ULONG InBufferLength, |
| _In_ ULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_INVALID_PARAMETER; |
| |
| UNREFERENCED_PARAMETER(OutBufferLength); |
| |
| if (InBufferLength >= sizeof(otIp6Prefix)) |
| { |
| const otIp6Prefix *aPrefix = (otIp6Prefix*)InBuffer; |
| |
| otIp6Address prefix = {0}; |
| memcpy_s(&prefix, sizeof(prefix), &aPrefix->mPrefix, aPrefix->mLength); |
| |
| status = |
| otLwfTunSendCommandForIrp( |
| pFilter, |
| pIrp, |
| NULL, |
| SPINEL_CMD_PROP_VALUE_REMOVE, |
| SPINEL_PROP_THREAD_ON_MESH_NETS, |
| sizeof(otIp6Address) + sizeof(uint8_t), |
| "6C", |
| &prefix, |
| aPrefix->mLength); |
| } |
| |
| return status; |
| } |
| |
| _IRQL_requires_max_(PASSIVE_LEVEL) |
| NTSTATUS |
| otLwfIoCtl_otAddExternalRoute( |
| _In_ PMS_FILTER pFilter, |
| _In_reads_bytes_(InBufferLength) |
| PUCHAR InBuffer, |
| _In_ ULONG InBufferLength, |
| _Out_writes_bytes_(*OutBufferLength) |
| PVOID OutBuffer, |
| _Inout_ PULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_INVALID_PARAMETER; |
| |
| UNREFERENCED_PARAMETER(OutBuffer); |
| *OutBufferLength = 0; |
| |
| if (InBufferLength >= sizeof(otExternalRouteConfig)) |
| { |
| status = ThreadErrorToNtstatus(otBorderRouterAddRoute(pFilter->otCtx, (otExternalRouteConfig*)InBuffer)); |
| } |
| |
| return status; |
| } |
| |
| _IRQL_requires_max_(PASSIVE_LEVEL) |
| NTSTATUS |
| otLwfTunIoCtl_otAddExternalRoute( |
| _In_ PMS_FILTER pFilter, |
| _In_ PIRP pIrp, |
| _In_reads_bytes_(InBufferLength) |
| PUCHAR InBuffer, |
| _In_ ULONG InBufferLength, |
| _In_ ULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_INVALID_PARAMETER; |
| |
| UNREFERENCED_PARAMETER(OutBufferLength); |
| |
| if (InBufferLength >= sizeof(otBorderRouterConfig)) |
| { |
| const otBorderRouterConfig *aConfig = (otBorderRouterConfig*)InBuffer; |
| |
| otIp6Address prefix = {0}; |
| memcpy_s(&prefix, sizeof(prefix), &aConfig->mPrefix.mPrefix, aConfig->mPrefix.mLength); |
| |
| uint8_t flags = (uint8_t)(aConfig->mPreference << kPreferenceOffset); |
| if (aConfig->mSlaac) flags |= kSlaacFlag; |
| if (aConfig->mDhcp) flags |= kDhcpFlag; |
| if (aConfig->mConfigure) flags |= kConfigureFlag; |
| if (aConfig->mDefaultRoute) flags |= kDefaultRouteFlag; |
| if (aConfig->mOnMesh) flags |= kOnMeshFlag; |
| |
| status = |
| otLwfTunSendCommandForIrp( |
| pFilter, |
| pIrp, |
| NULL, |
| SPINEL_CMD_PROP_VALUE_INSERT, |
| SPINEL_PROP_THREAD_OFF_MESH_ROUTES, |
| sizeof(otIp6Address) + 3 * sizeof(uint8_t), |
| "6CbC", |
| &prefix, |
| aConfig->mPrefix.mLength, |
| aConfig->mStable, |
| flags); |
| } |
| |
| return status; |
| } |
| |
| _IRQL_requires_max_(PASSIVE_LEVEL) |
| NTSTATUS |
| otLwfIoCtl_otRemoveExternalRoute( |
| _In_ PMS_FILTER pFilter, |
| _In_reads_bytes_(InBufferLength) |
| PUCHAR InBuffer, |
| _In_ ULONG InBufferLength, |
| _Out_writes_bytes_(*OutBufferLength) |
| PVOID OutBuffer, |
| _Inout_ PULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_INVALID_PARAMETER; |
| |
| UNREFERENCED_PARAMETER(OutBuffer); |
| *OutBufferLength = 0; |
| |
| if (InBufferLength >= sizeof(otIp6Prefix)) |
| { |
| status = ThreadErrorToNtstatus(otBorderRouterRemoveRoute(pFilter->otCtx, (otIp6Prefix*)InBuffer)); |
| } |
| |
| return status; |
| } |
| |
| _IRQL_requires_max_(PASSIVE_LEVEL) |
| NTSTATUS |
| otLwfTunIoCtl_otRemoveExternalRoute( |
| _In_ PMS_FILTER pFilter, |
| _In_ PIRP pIrp, |
| _In_reads_bytes_(InBufferLength) |
| PUCHAR InBuffer, |
| _In_ ULONG InBufferLength, |
| _In_ ULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_INVALID_PARAMETER; |
| |
| UNREFERENCED_PARAMETER(OutBufferLength); |
| |
| if (InBufferLength >= sizeof(otIp6Prefix)) |
| { |
| const otIp6Prefix *aPrefix = (otIp6Prefix*)InBuffer; |
| |
| otIp6Address prefix = {0}; |
| memcpy_s(&prefix, sizeof(prefix), &aPrefix->mPrefix, aPrefix->mLength); |
| |
| status = |
| otLwfTunSendCommandForIrp( |
| pFilter, |
| pIrp, |
| NULL, |
| SPINEL_CMD_PROP_VALUE_REMOVE, |
| SPINEL_PROP_THREAD_OFF_MESH_ROUTES, |
| sizeof(otIp6Address) + sizeof(uint8_t), |
| "6C", |
| &prefix, |
| aPrefix->mLength); |
| } |
| |
| return status; |
| } |
| |
| _IRQL_requires_max_(PASSIVE_LEVEL) |
| NTSTATUS |
| otLwfIoCtl_otSendServerData( |
| _In_ PMS_FILTER pFilter, |
| _In_reads_bytes_(InBufferLength) |
| PUCHAR InBuffer, |
| _In_ ULONG InBufferLength, |
| _Out_writes_bytes_(*OutBufferLength) |
| PVOID OutBuffer, |
| _Inout_ PULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_INVALID_PARAMETER; |
| |
| UNREFERENCED_PARAMETER(InBuffer); |
| UNREFERENCED_PARAMETER(InBufferLength); |
| UNREFERENCED_PARAMETER(OutBuffer); |
| *OutBufferLength = 0; |
| |
| status = ThreadErrorToNtstatus(otBorderRouterRegister(pFilter->otCtx)); |
| |
| return status; |
| } |
| |
| _IRQL_requires_max_(PASSIVE_LEVEL) |
| NTSTATUS |
| otLwfIoCtl_otContextIdReuseDelay( |
| _In_ PMS_FILTER pFilter, |
| _In_reads_bytes_(InBufferLength) |
| PUCHAR InBuffer, |
| _In_ ULONG InBufferLength, |
| _Out_writes_bytes_(*OutBufferLength) |
| PVOID OutBuffer, |
| _Inout_ PULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_INVALID_PARAMETER; |
| |
| if (InBufferLength >= sizeof(uint32_t)) |
| { |
| otThreadSetContextIdReuseDelay(pFilter->otCtx, *(uint32_t*)InBuffer); |
| status = STATUS_SUCCESS; |
| *OutBufferLength = 0; |
| } |
| else if (*OutBufferLength >= sizeof(uint32_t)) |
| { |
| *(uint32_t*)OutBuffer = otThreadGetContextIdReuseDelay(pFilter->otCtx); |
| status = STATUS_SUCCESS; |
| *OutBufferLength = sizeof(uint32_t); |
| } |
| else |
| { |
| *OutBufferLength = 0; |
| } |
| |
| return status; |
| } |
| |
| _IRQL_requires_max_(PASSIVE_LEVEL) |
| NTSTATUS |
| otLwfTunIoCtl_otContextIdReuseDelay( |
| _In_ PMS_FILTER pFilter, |
| _In_ PIRP pIrp, |
| _In_reads_bytes_(InBufferLength) |
| PUCHAR InBuffer, |
| _In_ ULONG InBufferLength, |
| _In_ ULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_INVALID_PARAMETER; |
| |
| if (InBufferLength >= sizeof(uint32_t)) |
| { |
| status = |
| otLwfTunSendCommandForIrp( |
| pFilter, |
| pIrp, |
| NULL, |
| SPINEL_CMD_PROP_VALUE_SET, |
| SPINEL_PROP_THREAD_CONTEXT_REUSE_DELAY, |
| sizeof(uint32_t), |
| SPINEL_DATATYPE_UINT32_S, |
| *(uint32_t*)InBuffer); |
| } |
| else if (OutBufferLength >= sizeof(uint32_t)) |
| { |
| status = |
| otLwfTunSendCommandForIrp( |
| pFilter, |
| pIrp, |
| otLwfTunIoCtl_otContextIdReuseDelay_Handler, |
| SPINEL_CMD_PROP_VALUE_GET, |
| SPINEL_PROP_THREAD_CONTEXT_REUSE_DELAY, |
| 0, |
| NULL); |
| } |
| |
| return status; |
| } |
| |
| _IRQL_requires_max_(DISPATCH_LEVEL) |
| NTSTATUS |
| otLwfTunIoCtl_otContextIdReuseDelay_Handler( |
| _In_ spinel_prop_key_t Key, |
| _In_reads_bytes_(DataLength) const uint8_t* Data, |
| _In_ spinel_size_t DataLength, |
| _Out_writes_bytes_(*OutBufferLength) |
| PVOID OutBuffer, |
| _Inout_ PULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_INVALID_PARAMETER; |
| if (Key == SPINEL_PROP_THREAD_CONTEXT_REUSE_DELAY) |
| { |
| if (try_spinel_datatype_unpack(Data, DataLength, SPINEL_DATATYPE_UINT32_S, (uint32_t*)OutBuffer)) |
| { |
| *OutBufferLength = sizeof(uint32_t); |
| status = STATUS_SUCCESS; |
| } |
| } |
| return status; |
| } |
| |
| _IRQL_requires_max_(PASSIVE_LEVEL) |
| NTSTATUS |
| otLwfIoCtl_otKeySequenceCounter( |
| _In_ PMS_FILTER pFilter, |
| _In_reads_bytes_(InBufferLength) |
| PUCHAR InBuffer, |
| _In_ ULONG InBufferLength, |
| _Out_writes_bytes_(*OutBufferLength) |
| PVOID OutBuffer, |
| _Inout_ PULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_INVALID_PARAMETER; |
| |
| if (InBufferLength >= sizeof(uint32_t)) |
| { |
| otThreadSetKeySequenceCounter(pFilter->otCtx, *(uint32_t*)InBuffer); |
| status = STATUS_SUCCESS; |
| *OutBufferLength = 0; |
| } |
| else if (*OutBufferLength >= sizeof(uint32_t)) |
| { |
| *(uint32_t*)OutBuffer = otThreadGetKeySequenceCounter(pFilter->otCtx); |
| status = STATUS_SUCCESS; |
| *OutBufferLength = sizeof(uint32_t); |
| } |
| else |
| { |
| *OutBufferLength = 0; |
| } |
| |
| return status; |
| } |
| |
| _IRQL_requires_max_(PASSIVE_LEVEL) |
| NTSTATUS |
| otLwfTunIoCtl_otKeySequenceCounter( |
| _In_ PMS_FILTER pFilter, |
| _In_ PIRP pIrp, |
| _In_reads_bytes_(InBufferLength) |
| PUCHAR InBuffer, |
| _In_ ULONG InBufferLength, |
| _In_ ULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_INVALID_PARAMETER; |
| |
| if (InBufferLength >= sizeof(uint32_t)) |
| { |
| status = |
| otLwfTunSendCommandForIrp( |
| pFilter, |
| pIrp, |
| NULL, |
| SPINEL_CMD_PROP_VALUE_SET, |
| SPINEL_PROP_NET_KEY_SEQUENCE_COUNTER, |
| sizeof(uint32_t), |
| SPINEL_DATATYPE_UINT32_S, |
| *(uint32_t*)InBuffer); |
| } |
| else if (OutBufferLength >= sizeof(uint32_t)) |
| { |
| status = |
| otLwfTunSendCommandForIrp( |
| pFilter, |
| pIrp, |
| otLwfTunIoCtl_otKeySequenceCounter_Handler, |
| SPINEL_CMD_PROP_VALUE_GET, |
| SPINEL_PROP_NET_KEY_SEQUENCE_COUNTER, |
| 0, |
| NULL); |
| } |
| |
| return status; |
| } |
| |
| _IRQL_requires_max_(DISPATCH_LEVEL) |
| NTSTATUS |
| otLwfTunIoCtl_otKeySequenceCounter_Handler( |
| _In_ spinel_prop_key_t Key, |
| _In_reads_bytes_(DataLength) const uint8_t* Data, |
| _In_ spinel_size_t DataLength, |
| _Out_writes_bytes_(*OutBufferLength) |
| PVOID OutBuffer, |
| _Inout_ PULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_INVALID_PARAMETER; |
| if (Key == SPINEL_PROP_NET_KEY_SEQUENCE_COUNTER) |
| { |
| if (try_spinel_datatype_unpack(Data, DataLength, SPINEL_DATATYPE_UINT32_S, (uint32_t*)OutBuffer)) |
| { |
| *OutBufferLength = sizeof(uint32_t); |
| status = STATUS_SUCCESS; |
| } |
| } |
| return status; |
| } |
| |
| _IRQL_requires_max_(PASSIVE_LEVEL) |
| NTSTATUS |
| otLwfIoCtl_otNetworkIdTimeout( |
| _In_ PMS_FILTER pFilter, |
| _In_reads_bytes_(InBufferLength) |
| PUCHAR InBuffer, |
| _In_ ULONG InBufferLength, |
| _Out_writes_bytes_(*OutBufferLength) |
| PVOID OutBuffer, |
| _Inout_ PULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_INVALID_PARAMETER; |
| |
| if (InBufferLength >= sizeof(uint8_t)) |
| { |
| otThreadSetNetworkIdTimeout(pFilter->otCtx, *(uint8_t*)InBuffer); |
| status = STATUS_SUCCESS; |
| *OutBufferLength = 0; |
| } |
| else if (*OutBufferLength >= sizeof(uint8_t)) |
| { |
| *(uint8_t*)OutBuffer = otThreadGetNetworkIdTimeout(pFilter->otCtx); |
| status = STATUS_SUCCESS; |
| *OutBufferLength = sizeof(uint8_t); |
| } |
| else |
| { |
| *OutBufferLength = 0; |
| } |
| |
| return status; |
| } |
| |
| _IRQL_requires_max_(PASSIVE_LEVEL) |
| NTSTATUS |
| otLwfTunIoCtl_otNetworkIdTimeout( |
| _In_ PMS_FILTER pFilter, |
| _In_ PIRP pIrp, |
| _In_reads_bytes_(InBufferLength) |
| PUCHAR InBuffer, |
| _In_ ULONG InBufferLength, |
| _In_ ULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_INVALID_PARAMETER; |
| |
| if (InBufferLength >= sizeof(uint8_t)) |
| { |
| status = |
| otLwfTunSendCommandForIrp( |
| pFilter, |
| pIrp, |
| NULL, |
| SPINEL_CMD_PROP_VALUE_SET, |
| SPINEL_PROP_THREAD_NETWORK_ID_TIMEOUT, |
| sizeof(uint8_t), |
| SPINEL_DATATYPE_UINT8_S, |
| *(uint8_t*)InBuffer); |
| } |
| else if (OutBufferLength >= sizeof(uint8_t)) |
| { |
| status = |
| otLwfTunSendCommandForIrp( |
| pFilter, |
| pIrp, |
| otLwfTunIoCtl_otNetworkIdTimeout_Handler, |
| SPINEL_CMD_PROP_VALUE_GET, |
| SPINEL_PROP_THREAD_NETWORK_ID_TIMEOUT, |
| 0, |
| NULL); |
| } |
| |
| return status; |
| } |
| |
| _IRQL_requires_max_(DISPATCH_LEVEL) |
| NTSTATUS |
| otLwfTunIoCtl_otNetworkIdTimeout_Handler( |
| _In_ spinel_prop_key_t Key, |
| _In_reads_bytes_(DataLength) const uint8_t* Data, |
| _In_ spinel_size_t DataLength, |
| _Out_writes_bytes_(*OutBufferLength) |
| PVOID OutBuffer, |
| _Inout_ PULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_INVALID_PARAMETER; |
| if (Key == SPINEL_PROP_THREAD_NETWORK_ID_TIMEOUT) |
| { |
| if (try_spinel_datatype_unpack(Data, DataLength, SPINEL_DATATYPE_UINT8_S, (uint8_t*)OutBuffer)) |
| { |
| *OutBufferLength = sizeof(uint8_t); |
| status = STATUS_SUCCESS; |
| } |
| } |
| return status; |
| } |
| |
| _IRQL_requires_max_(PASSIVE_LEVEL) |
| NTSTATUS |
| otLwfIoCtl_otRouterUpgradeThreshold( |
| _In_ PMS_FILTER pFilter, |
| _In_reads_bytes_(InBufferLength) |
| PUCHAR InBuffer, |
| _In_ ULONG InBufferLength, |
| _Out_writes_bytes_(*OutBufferLength) |
| PVOID OutBuffer, |
| _Inout_ PULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_INVALID_PARAMETER; |
| |
| if (InBufferLength >= sizeof(uint8_t)) |
| { |
| otThreadSetRouterUpgradeThreshold(pFilter->otCtx, *(uint8_t*)InBuffer); |
| status = STATUS_SUCCESS; |
| *OutBufferLength = 0; |
| } |
| else if (*OutBufferLength >= sizeof(uint8_t)) |
| { |
| *(uint8_t*)OutBuffer = otThreadGetRouterUpgradeThreshold(pFilter->otCtx); |
| status = STATUS_SUCCESS; |
| *OutBufferLength = sizeof(uint8_t); |
| } |
| else |
| { |
| *OutBufferLength = 0; |
| } |
| |
| return status; |
| } |
| |
| _IRQL_requires_max_(PASSIVE_LEVEL) |
| NTSTATUS |
| otLwfTunIoCtl_otRouterUpgradeThreshold( |
| _In_ PMS_FILTER pFilter, |
| _In_ PIRP pIrp, |
| _In_reads_bytes_(InBufferLength) |
| PUCHAR InBuffer, |
| _In_ ULONG InBufferLength, |
| _In_ ULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_INVALID_PARAMETER; |
| |
| if (InBufferLength >= sizeof(uint8_t)) |
| { |
| status = |
| otLwfTunSendCommandForIrp( |
| pFilter, |
| pIrp, |
| NULL, |
| SPINEL_CMD_PROP_VALUE_SET, |
| SPINEL_PROP_THREAD_ROUTER_UPGRADE_THRESHOLD, |
| sizeof(uint8_t), |
| SPINEL_DATATYPE_UINT8_S, |
| *(uint8_t*)InBuffer); |
| } |
| else if (OutBufferLength >= sizeof(uint8_t)) |
| { |
| status = |
| otLwfTunSendCommandForIrp( |
| pFilter, |
| pIrp, |
| otLwfTunIoCtl_otRouterUpgradeThreshold_Handler, |
| SPINEL_CMD_PROP_VALUE_GET, |
| SPINEL_PROP_THREAD_ROUTER_UPGRADE_THRESHOLD, |
| 0, |
| NULL); |
| } |
| |
| return status; |
| } |
| |
| _IRQL_requires_max_(DISPATCH_LEVEL) |
| NTSTATUS |
| otLwfTunIoCtl_otRouterUpgradeThreshold_Handler( |
| _In_ spinel_prop_key_t Key, |
| _In_reads_bytes_(DataLength) const uint8_t* Data, |
| _In_ spinel_size_t DataLength, |
| _Out_writes_bytes_(*OutBufferLength) |
| PVOID OutBuffer, |
| _Inout_ PULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_INVALID_PARAMETER; |
| if (Key == SPINEL_PROP_THREAD_ROUTER_UPGRADE_THRESHOLD) |
| { |
| if (try_spinel_datatype_unpack(Data, DataLength, SPINEL_DATATYPE_UINT8_S, (uint8_t*)OutBuffer)) |
| { |
| *OutBufferLength = sizeof(uint8_t); |
| status = STATUS_SUCCESS; |
| } |
| } |
| return status; |
| } |
| |
| _IRQL_requires_max_(PASSIVE_LEVEL) |
| NTSTATUS |
| otLwfIoCtl_otRouterDowngradeThreshold( |
| _In_ PMS_FILTER pFilter, |
| _In_reads_bytes_(InBufferLength) |
| PUCHAR InBuffer, |
| _In_ ULONG InBufferLength, |
| _Out_writes_bytes_(*OutBufferLength) |
| PVOID OutBuffer, |
| _Inout_ PULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_INVALID_PARAMETER; |
| |
| if (InBufferLength >= sizeof(uint8_t)) |
| { |
| otThreadSetRouterDowngradeThreshold(pFilter->otCtx, *(uint8_t*)InBuffer); |
| status = STATUS_SUCCESS; |
| *OutBufferLength = 0; |
| } |
| else if (*OutBufferLength >= sizeof(uint8_t)) |
| { |
| *(uint8_t*)OutBuffer = otThreadGetRouterDowngradeThreshold(pFilter->otCtx); |
| status = STATUS_SUCCESS; |
| *OutBufferLength = sizeof(uint8_t); |
| } |
| else |
| { |
| *OutBufferLength = 0; |
| } |
| |
| return status; |
| } |
| |
| _IRQL_requires_max_(PASSIVE_LEVEL) |
| NTSTATUS |
| otLwfTunIoCtl_otRouterDowngradeThreshold( |
| _In_ PMS_FILTER pFilter, |
| _In_ PIRP pIrp, |
| _In_reads_bytes_(InBufferLength) |
| PUCHAR InBuffer, |
| _In_ ULONG InBufferLength, |
| _In_ ULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_INVALID_PARAMETER; |
| |
| if (InBufferLength >= sizeof(uint8_t)) |
| { |
| status = |
| otLwfTunSendCommandForIrp( |
| pFilter, |
| pIrp, |
| NULL, |
| SPINEL_CMD_PROP_VALUE_SET, |
| SPINEL_PROP_THREAD_ROUTER_DOWNGRADE_THRESHOLD, |
| sizeof(uint8_t), |
| SPINEL_DATATYPE_UINT8_S, |
| *(uint8_t*)InBuffer); |
| } |
| else if (OutBufferLength >= sizeof(uint8_t)) |
| { |
| status = |
| otLwfTunSendCommandForIrp( |
| pFilter, |
| pIrp, |
| otLwfTunIoCtl_otRouterDowngradeThreshold_Handler, |
| SPINEL_CMD_PROP_VALUE_GET, |
| SPINEL_PROP_THREAD_ROUTER_DOWNGRADE_THRESHOLD, |
| 0, |
| NULL); |
| } |
| |
| return status; |
| } |
| |
| _IRQL_requires_max_(DISPATCH_LEVEL) |
| NTSTATUS |
| otLwfTunIoCtl_otRouterDowngradeThreshold_Handler( |
| _In_ spinel_prop_key_t Key, |
| _In_reads_bytes_(DataLength) const uint8_t* Data, |
| _In_ spinel_size_t DataLength, |
| _Out_writes_bytes_(*OutBufferLength) |
| PVOID OutBuffer, |
| _Inout_ PULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_INVALID_PARAMETER; |
| if (Key == SPINEL_PROP_THREAD_ROUTER_DOWNGRADE_THRESHOLD) |
| { |
| if (try_spinel_datatype_unpack(Data, DataLength, SPINEL_DATATYPE_UINT8_S, (uint8_t*)OutBuffer)) |
| { |
| *OutBufferLength = sizeof(uint8_t); |
| status = STATUS_SUCCESS; |
| } |
| } |
| return status; |
| } |
| |
| _IRQL_requires_max_(PASSIVE_LEVEL) |
| NTSTATUS |
| otLwfIoCtl_otReleaseRouterId( |
| _In_ PMS_FILTER pFilter, |
| _In_reads_bytes_(InBufferLength) |
| PUCHAR InBuffer, |
| _In_ ULONG InBufferLength, |
| _Out_writes_bytes_(*OutBufferLength) |
| PVOID OutBuffer, |
| _Inout_ PULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_INVALID_PARAMETER; |
| |
| UNREFERENCED_PARAMETER(OutBuffer); |
| *OutBufferLength = 0; |
| |
| if (InBufferLength >= sizeof(uint8_t)) |
| { |
| status = ThreadErrorToNtstatus(otThreadReleaseRouterId(pFilter->otCtx, *(uint8_t*)InBuffer)); |
| } |
| |
| return status; |
| } |
| |
| _IRQL_requires_max_(PASSIVE_LEVEL) |
| NTSTATUS |
| otLwfTunIoCtl_otReleaseRouterId( |
| _In_ PMS_FILTER pFilter, |
| _In_ PIRP pIrp, |
| _In_reads_bytes_(InBufferLength) |
| PUCHAR InBuffer, |
| _In_ ULONG InBufferLength, |
| _In_ ULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_INVALID_PARAMETER; |
| |
| UNREFERENCED_PARAMETER(OutBufferLength); |
| |
| if (InBufferLength >= sizeof(uint8_t)) |
| { |
| status = |
| otLwfTunSendCommandForIrp( |
| pFilter, |
| pIrp, |
| NULL, |
| SPINEL_CMD_PROP_VALUE_REMOVE, |
| SPINEL_PROP_THREAD_ACTIVE_ROUTER_IDS, |
| sizeof(uint8_t), |
| SPINEL_DATATYPE_UINT8_S, |
| *(uint8_t*)InBuffer); |
| } |
| |
| return status; |
| } |
| |
| _IRQL_requires_max_(PASSIVE_LEVEL) |
| NTSTATUS |
| otLwfIoCtl_otMacWhitelistEnabled( |
| _In_ PMS_FILTER pFilter, |
| _In_reads_bytes_(InBufferLength) |
| PUCHAR InBuffer, |
| _In_ ULONG InBufferLength, |
| _Out_writes_bytes_(*OutBufferLength) |
| PVOID OutBuffer, |
| _Inout_ PULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_INVALID_PARAMETER; |
| |
| if (InBufferLength >= sizeof(BOOLEAN)) |
| { |
| BOOLEAN aEnabled = *(BOOLEAN*)InBuffer; |
| otLinkSetWhitelistEnabled(pFilter->otCtx, aEnabled); |
| status = STATUS_SUCCESS; |
| *OutBufferLength = 0; |
| } |
| else if (*OutBufferLength >= sizeof(BOOLEAN)) |
| { |
| *(BOOLEAN*)OutBuffer = otLinkIsWhitelistEnabled(pFilter->otCtx) ? TRUE : FALSE; |
| status = STATUS_SUCCESS; |
| *OutBufferLength = sizeof(BOOLEAN); |
| } |
| else |
| { |
| *OutBufferLength = 0; |
| } |
| |
| return status; |
| } |
| |
| _IRQL_requires_max_(PASSIVE_LEVEL) |
| NTSTATUS |
| otLwfTunIoCtl_otMacWhitelistEnabled( |
| _In_ PMS_FILTER pFilter, |
| _In_ PIRP pIrp, |
| _In_reads_bytes_(InBufferLength) |
| PUCHAR InBuffer, |
| _In_ ULONG InBufferLength, |
| _In_ ULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_INVALID_PARAMETER; |
| |
| if (InBufferLength >= sizeof(BOOLEAN)) |
| { |
| status = |
| otLwfTunSendCommandForIrp( |
| pFilter, |
| pIrp, |
| NULL, |
| SPINEL_CMD_PROP_VALUE_SET, |
| SPINEL_PROP_MAC_WHITELIST_ENABLED, |
| sizeof(BOOLEAN), |
| SPINEL_DATATYPE_BOOL_S, |
| *(BOOLEAN*)InBuffer); |
| } |
| else if (OutBufferLength >= sizeof(BOOLEAN)) |
| { |
| status = |
| otLwfTunSendCommandForIrp( |
| pFilter, |
| pIrp, |
| otLwfTunIoCtl_otMacWhitelistEnabled_Handler, |
| SPINEL_CMD_PROP_VALUE_GET, |
| SPINEL_PROP_MAC_WHITELIST_ENABLED, |
| 0, |
| NULL); |
| } |
| |
| return status; |
| } |
| |
| _IRQL_requires_max_(DISPATCH_LEVEL) |
| NTSTATUS |
| otLwfTunIoCtl_otMacWhitelistEnabled_Handler( |
| _In_ spinel_prop_key_t Key, |
| _In_reads_bytes_(DataLength) const uint8_t* Data, |
| _In_ spinel_size_t DataLength, |
| _Out_writes_bytes_(*OutBufferLength) |
| PVOID OutBuffer, |
| _Inout_ PULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_INVALID_PARAMETER; |
| if (Key == SPINEL_PROP_MAC_WHITELIST_ENABLED) |
| { |
| if (try_spinel_datatype_unpack(Data, DataLength, SPINEL_DATATYPE_BOOL_S, (BOOLEAN*)OutBuffer)) |
| { |
| *OutBufferLength = sizeof(BOOLEAN); |
| status = STATUS_SUCCESS; |
| } |
| } |
| return status; |
| } |
| |
| _IRQL_requires_max_(PASSIVE_LEVEL) |
| NTSTATUS |
| otLwfIoCtl_otAddMacWhitelist( |
| _In_ PMS_FILTER pFilter, |
| _In_reads_bytes_(InBufferLength) |
| PUCHAR InBuffer, |
| _In_ ULONG InBufferLength, |
| _Out_writes_bytes_(*OutBufferLength) |
| PVOID OutBuffer, |
| _Inout_ PULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_INVALID_PARAMETER; |
| |
| UNREFERENCED_PARAMETER(OutBuffer); |
| *OutBufferLength = 0; |
| |
| if (InBufferLength >= sizeof(otExtAddress) + sizeof(int8_t)) |
| { |
| int8_t aRssi = *(int8_t*)(InBuffer + sizeof(otExtAddress)); |
| status = ThreadErrorToNtstatus(otLinkAddWhitelistRssi(pFilter->otCtx, (uint8_t*)InBuffer, aRssi)); |
| } |
| else if (InBufferLength >= sizeof(otExtAddress)) |
| { |
| status = ThreadErrorToNtstatus(otLinkAddWhitelist(pFilter->otCtx, (uint8_t*)InBuffer)); |
| } |
| |
| return status; |
| } |
| |
| #define RSSI_OVERRIDE_DISABLED 127 // Used for PROP_MAC_WHITELIST |
| |
| _IRQL_requires_max_(PASSIVE_LEVEL) |
| NTSTATUS |
| otLwfTunIoCtl_otAddMacWhitelist( |
| _In_ PMS_FILTER pFilter, |
| _In_ PIRP pIrp, |
| _In_reads_bytes_(InBufferLength) |
| PUCHAR InBuffer, |
| _In_ ULONG InBufferLength, |
| _In_ ULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_INVALID_PARAMETER; |
| |
| UNREFERENCED_PARAMETER(OutBufferLength); |
| |
| if (InBufferLength >= sizeof(otExtAddress)) |
| { |
| int8_t aRssi = RSSI_OVERRIDE_DISABLED; |
| if (InBufferLength >= sizeof(otExtAddress) + sizeof(int8_t)) |
| { |
| aRssi = *(int8_t*)(InBuffer + sizeof(otExtAddress)); |
| } |
| |
| status = |
| otLwfTunSendCommandForIrp( |
| pFilter, |
| pIrp, |
| NULL, |
| SPINEL_CMD_PROP_VALUE_INSERT, |
| SPINEL_PROP_MAC_WHITELIST, |
| sizeof(otExtAddress) + sizeof(int8_t), |
| "Ec", |
| (otExtAddress*)InBuffer, |
| &aRssi); |
| } |
| |
| return status; |
| } |
| |
| _IRQL_requires_max_(PASSIVE_LEVEL) |
| NTSTATUS |
| otLwfIoCtl_otRemoveMacWhitelist( |
| _In_ PMS_FILTER pFilter, |
| _In_reads_bytes_(InBufferLength) |
| PUCHAR InBuffer, |
| _In_ ULONG InBufferLength, |
| _Out_writes_bytes_(*OutBufferLength) |
| PVOID OutBuffer, |
| _Inout_ PULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_INVALID_PARAMETER; |
| |
| UNREFERENCED_PARAMETER(OutBuffer); |
| *OutBufferLength = 0; |
| |
| if (InBufferLength >= sizeof(otExtAddress)) |
| { |
| otLinkRemoveWhitelist(pFilter->otCtx, (uint8_t*)InBuffer); |
| status = STATUS_SUCCESS; |
| } |
| |
| return status; |
| } |
| |
| _IRQL_requires_max_(PASSIVE_LEVEL) |
| NTSTATUS |
| otLwfTunIoCtl_otRemoveMacWhitelist( |
| _In_ PMS_FILTER pFilter, |
| _In_ PIRP pIrp, |
| _In_reads_bytes_(InBufferLength) |
| PUCHAR InBuffer, |
| _In_ ULONG InBufferLength, |
| _In_ ULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_INVALID_PARAMETER; |
| |
| UNREFERENCED_PARAMETER(OutBufferLength); |
| |
| if (InBufferLength >= sizeof(otExtAddress)) |
| { |
| status = |
| otLwfTunSendCommandForIrp( |
| pFilter, |
| pIrp, |
| NULL, |
| SPINEL_CMD_PROP_VALUE_REMOVE, |
| SPINEL_PROP_MAC_WHITELIST, |
| sizeof(otExtAddress), |
| "E", |
| (otExtAddress*)InBuffer); |
| } |
| |
| return status; |
| } |
| |
| _IRQL_requires_max_(PASSIVE_LEVEL) |
| NTSTATUS |
| otLwfIoCtl_otMacWhitelistEntry( |
| _In_ PMS_FILTER pFilter, |
| _In_reads_bytes_(InBufferLength) |
| PUCHAR InBuffer, |
| _In_ ULONG InBufferLength, |
| _Out_writes_bytes_(*OutBufferLength) |
| PVOID OutBuffer, |
| _Inout_ PULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_INVALID_PARAMETER; |
| |
| if (InBufferLength >= sizeof(uint8_t) && |
| *OutBufferLength >= sizeof(otMacWhitelistEntry)) |
| { |
| status = ThreadErrorToNtstatus( |
| otLinkGetWhitelistEntry( |
| pFilter->otCtx, |
| *(uint8_t*)InBuffer, |
| (otMacWhitelistEntry*)OutBuffer) |
| ); |
| *OutBufferLength = sizeof(otMacWhitelistEntry); |
| } |
| else |
| { |
| *OutBufferLength = 0; |
| } |
| |
| return status; |
| } |
| |
| _IRQL_requires_max_(PASSIVE_LEVEL) |
| NTSTATUS |
| otLwfIoCtl_otClearMacWhitelist( |
| _In_ PMS_FILTER pFilter, |
| _In_reads_bytes_(InBufferLength) |
| PUCHAR InBuffer, |
| _In_ ULONG InBufferLength, |
| _Out_writes_bytes_(*OutBufferLength) |
| PVOID OutBuffer, |
| _Inout_ PULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_SUCCESS; |
| |
| UNREFERENCED_PARAMETER(InBuffer); |
| UNREFERENCED_PARAMETER(InBufferLength); |
| UNREFERENCED_PARAMETER(OutBuffer); |
| *OutBufferLength = 0; |
| |
| otLinkClearWhitelist(pFilter->otCtx); |
| |
| return status; |
| } |
| |
| _IRQL_requires_max_(PASSIVE_LEVEL) |
| NTSTATUS |
| otLwfTunIoCtl_otClearMacWhitelist( |
| _In_ PMS_FILTER pFilter, |
| _In_ PIRP pIrp, |
| _In_reads_bytes_(InBufferLength) |
| PUCHAR InBuffer, |
| _In_ ULONG InBufferLength, |
| _In_ ULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_INVALID_PARAMETER; |
| |
| UNREFERENCED_PARAMETER(InBuffer); |
| UNREFERENCED_PARAMETER(InBufferLength); |
| UNREFERENCED_PARAMETER(OutBufferLength); |
| |
| status = |
| otLwfTunSendCommandForIrp( |
| pFilter, |
| pIrp, |
| NULL, |
| SPINEL_CMD_PROP_VALUE_SET, |
| SPINEL_PROP_MAC_WHITELIST, |
| 0, |
| NULL); |
| |
| return status; |
| } |
| |
| _IRQL_requires_max_(PASSIVE_LEVEL) |
| NTSTATUS |
| otLwfIoCtl_otDeviceRole( |
| _In_ PMS_FILTER pFilter, |
| _In_reads_bytes_(InBufferLength) |
| PUCHAR InBuffer, |
| _In_ ULONG InBufferLength, |
| _Out_writes_bytes_(*OutBufferLength) |
| PVOID OutBuffer, |
| _Inout_ PULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_INVALID_PARAMETER; |
| |
| if (InBufferLength >= sizeof(uint8_t)) |
| { |
| otDeviceRole role = *(uint8_t*)InBuffer; |
| |
| InBufferLength -= sizeof(uint8_t); |
| InBuffer = InBuffer + sizeof(uint8_t); |
| |
| if (role == OT_DEVICE_ROLE_LEADER) |
| { |
| status = ThreadErrorToNtstatus( |
| otThreadBecomeLeader(pFilter->otCtx) |
| ); |
| } |
| else if (role == OT_DEVICE_ROLE_ROUTER) |
| { |
| status = ThreadErrorToNtstatus( |
| otThreadBecomeRouter(pFilter->otCtx) |
| ); |
| } |
| else if (role == OT_DEVICE_ROLE_CHILD) |
| { |
| status = ThreadErrorToNtstatus( |
| otThreadBecomeChild(pFilter->otCtx) |
| ); |
| } |
| else if (role == OT_DEVICE_ROLE_DETACHED) |
| { |
| status = ThreadErrorToNtstatus( |
| otThreadBecomeDetached(pFilter->otCtx) |
| ); |
| } |
| *OutBufferLength = 0; |
| } |
| else if (*OutBufferLength >= sizeof(uint8_t)) |
| { |
| *(uint8_t*)OutBuffer = (uint8_t)otThreadGetDeviceRole(pFilter->otCtx); |
| *OutBufferLength = sizeof(uint8_t); |
| status = STATUS_SUCCESS; |
| } |
| else |
| { |
| *OutBufferLength = 0; |
| } |
| |
| return status; |
| } |
| |
| _IRQL_requires_max_(PASSIVE_LEVEL) |
| NTSTATUS |
| otLwfTunIoCtl_otDeviceRole( |
| _In_ PMS_FILTER pFilter, |
| _In_ PIRP pIrp, |
| _In_reads_bytes_(InBufferLength) |
| PUCHAR InBuffer, |
| _In_ ULONG InBufferLength, |
| _In_ ULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_INVALID_PARAMETER; |
| |
| if (InBufferLength >= sizeof(uint8_t)) |
| { |
| otDeviceRole role = *(uint8_t*)InBuffer; |
| uint8_t spinel_role = SPINEL_NET_ROLE_DETACHED; |
| |
| switch (role) |
| { |
| case OT_DEVICE_ROLE_CHILD: |
| spinel_role = SPINEL_NET_ROLE_CHILD; |
| break; |
| case OT_DEVICE_ROLE_ROUTER: |
| spinel_role = SPINEL_NET_ROLE_ROUTER; |
| break; |
| case OT_DEVICE_ROLE_LEADER: |
| spinel_role = SPINEL_NET_ROLE_LEADER; |
| break; |
| } |
| |
| status = |
| otLwfTunSendCommandForIrp( |
| pFilter, |
| pIrp, |
| NULL, |
| SPINEL_CMD_PROP_VALUE_SET, |
| SPINEL_PROP_NET_ROLE, |
| sizeof(uint8_t), |
| SPINEL_DATATYPE_UINT8_S, |
| spinel_role); |
| } |
| else if (OutBufferLength >= sizeof(uint8_t)) |
| { |
| status = |
| otLwfTunSendCommandForIrp( |
| pFilter, |
| pIrp, |
| otLwfTunIoCtl_otDeviceRole_Handler, |
| SPINEL_CMD_PROP_VALUE_GET, |
| SPINEL_PROP_NET_ROLE, |
| 0, |
| NULL); |
| } |
| |
| return status; |
| } |
| |
| _IRQL_requires_max_(DISPATCH_LEVEL) |
| NTSTATUS |
| otLwfTunIoCtl_otDeviceRole_Handler( |
| _In_ spinel_prop_key_t Key, |
| _In_reads_bytes_(DataLength) const uint8_t* Data, |
| _In_ spinel_size_t DataLength, |
| _Out_writes_bytes_(*OutBufferLength) |
| PVOID OutBuffer, |
| _Inout_ PULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_INVALID_PARAMETER; |
| if (Key == SPINEL_PROP_NET_ROLE) |
| { |
| uint8_t spinel_role = 0; |
| if (try_spinel_datatype_unpack(Data, DataLength, SPINEL_DATATYPE_UINT8_S, &spinel_role)) |
| { |
| switch (spinel_role) |
| { |
| default: |
| case SPINEL_NET_ROLE_DETACHED: |
| *(uint8_t*)OutBuffer = OT_DEVICE_ROLE_DETACHED; |
| break; |
| case SPINEL_NET_ROLE_CHILD: |
| *(uint8_t*)OutBuffer = OT_DEVICE_ROLE_CHILD; |
| break; |
| case SPINEL_NET_ROLE_ROUTER: |
| *(uint8_t*)OutBuffer = OT_DEVICE_ROLE_ROUTER; |
| break; |
| case SPINEL_NET_ROLE_LEADER: |
| *(uint8_t*)OutBuffer = OT_DEVICE_ROLE_LEADER; |
| break; |
| } |
| |
| *OutBufferLength = sizeof(uint8_t); |
| status = STATUS_SUCCESS; |
| } |
| } |
| return status; |
| } |
| |
| _IRQL_requires_max_(PASSIVE_LEVEL) |
| NTSTATUS |
| otLwfIoCtl_otChildInfoById( |
| _In_ PMS_FILTER pFilter, |
| _In_reads_bytes_(InBufferLength) |
| PUCHAR InBuffer, |
| _In_ ULONG InBufferLength, |
| _Out_writes_bytes_(*OutBufferLength) |
| PVOID OutBuffer, |
| _Inout_ PULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_INVALID_PARAMETER; |
| |
| if (InBufferLength >= sizeof(uint16_t) && |
| *OutBufferLength >= sizeof(otChildInfo)) |
| { |
| status = ThreadErrorToNtstatus( |
| otThreadGetChildInfoById( |
| pFilter->otCtx, |
| *(uint16_t*)InBuffer, |
| (otChildInfo*)OutBuffer) |
| ); |
| *OutBufferLength = sizeof(otChildInfo); |
| } |
| else |
| { |
| *OutBufferLength = 0; |
| } |
| |
| return status; |
| } |
| |
| _IRQL_requires_max_(PASSIVE_LEVEL) |
| NTSTATUS |
| otLwfIoCtl_otChildInfoByIndex( |
| _In_ PMS_FILTER pFilter, |
| _In_reads_bytes_(InBufferLength) |
| PUCHAR InBuffer, |
| _In_ ULONG InBufferLength, |
| _Out_writes_bytes_(*OutBufferLength) |
| PVOID OutBuffer, |
| _Inout_ PULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_INVALID_PARAMETER; |
| |
| if (InBufferLength >= sizeof(uint8_t) && |
| *OutBufferLength >= sizeof(otChildInfo)) |
| { |
| status = ThreadErrorToNtstatus( |
| otThreadGetChildInfoByIndex( |
| pFilter->otCtx, |
| *(uint8_t*)InBuffer, |
| (otChildInfo*)OutBuffer) |
| ); |
| *OutBufferLength = sizeof(otChildInfo); |
| } |
| else |
| { |
| *OutBufferLength = 0; |
| } |
| |
| return status; |
| } |
| |
| _IRQL_requires_max_(PASSIVE_LEVEL) |
| NTSTATUS |
| otLwfIoCtl_otEidCacheEntry( |
| _In_ PMS_FILTER pFilter, |
| _In_reads_bytes_(InBufferLength) |
| PUCHAR InBuffer, |
| _In_ ULONG InBufferLength, |
| _Out_writes_bytes_(*OutBufferLength) |
| PVOID OutBuffer, |
| _Inout_ PULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_INVALID_PARAMETER; |
| |
| if (InBufferLength >= sizeof(uint8_t) && |
| *OutBufferLength >= sizeof(otEidCacheEntry)) |
| { |
| status = ThreadErrorToNtstatus( |
| otThreadGetEidCacheEntry( |
| pFilter->otCtx, |
| *(uint8_t*)InBuffer, |
| (otEidCacheEntry*)OutBuffer) |
| ); |
| *OutBufferLength = sizeof(otEidCacheEntry); |
| } |
| else |
| { |
| *OutBufferLength = 0; |
| } |
| |
| return status; |
| } |
| |
| _IRQL_requires_max_(PASSIVE_LEVEL) |
| NTSTATUS |
| otLwfIoCtl_otLeaderData( |
| _In_ PMS_FILTER pFilter, |
| _In_reads_bytes_(InBufferLength) |
| PUCHAR InBuffer, |
| _In_ ULONG InBufferLength, |
| _Out_writes_bytes_(*OutBufferLength) |
| PVOID OutBuffer, |
| _Inout_ PULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_INVALID_PARAMETER; |
| |
| UNREFERENCED_PARAMETER(InBuffer); |
| UNREFERENCED_PARAMETER(InBufferLength); |
| |
| if (*OutBufferLength >= sizeof(otLeaderData)) |
| { |
| status = ThreadErrorToNtstatus(otThreadGetLeaderData(pFilter->otCtx, (otLeaderData*)OutBuffer)); |
| *OutBufferLength = sizeof(otLeaderData); |
| } |
| else |
| { |
| *OutBufferLength = 0; |
| } |
| |
| return status; |
| } |
| |
| _IRQL_requires_max_(PASSIVE_LEVEL) |
| NTSTATUS |
| otLwfIoCtl_otLeaderRouterId( |
| _In_ PMS_FILTER pFilter, |
| _In_reads_bytes_(InBufferLength) |
| PUCHAR InBuffer, |
| _In_ ULONG InBufferLength, |
| _Out_writes_bytes_(*OutBufferLength) |
| PVOID OutBuffer, |
| _Inout_ PULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_INVALID_PARAMETER; |
| |
| UNREFERENCED_PARAMETER(InBuffer); |
| UNREFERENCED_PARAMETER(InBufferLength); |
| |
| if (*OutBufferLength >= sizeof(uint8_t)) |
| { |
| *(uint8_t*)OutBuffer = otThreadGetLeaderRouterId(pFilter->otCtx); |
| *OutBufferLength = sizeof(uint8_t); |
| status = STATUS_SUCCESS; |
| } |
| else |
| { |
| *OutBufferLength = 0; |
| } |
| |
| return status; |
| } |
| |
| _IRQL_requires_max_(PASSIVE_LEVEL) |
| NTSTATUS |
| otLwfTunIoCtl_otLeaderRouterId( |
| _In_ PMS_FILTER pFilter, |
| _In_ PIRP pIrp, |
| _In_reads_bytes_(InBufferLength) |
| PUCHAR InBuffer, |
| _In_ ULONG InBufferLength, |
| _In_ ULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_INVALID_PARAMETER; |
| |
| UNREFERENCED_PARAMETER(InBuffer); |
| UNREFERENCED_PARAMETER(InBufferLength); |
| |
| if (OutBufferLength >= sizeof(uint8_t)) |
| { |
| status = |
| otLwfTunSendCommandForIrp( |
| pFilter, |
| pIrp, |
| otLwfTunIoCtl_otLeaderRouterId_Handler, |
| SPINEL_CMD_PROP_VALUE_GET, |
| SPINEL_PROP_THREAD_LEADER_RID, |
| 0, |
| NULL); |
| } |
| |
| return status; |
| } |
| |
| _IRQL_requires_max_(DISPATCH_LEVEL) |
| NTSTATUS |
| otLwfTunIoCtl_otLeaderRouterId_Handler( |
| _In_ spinel_prop_key_t Key, |
| _In_reads_bytes_(DataLength) const uint8_t* Data, |
| _In_ spinel_size_t DataLength, |
| _Out_writes_bytes_(*OutBufferLength) |
| PVOID OutBuffer, |
| _Inout_ PULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_INVALID_PARAMETER; |
| if (Key == SPINEL_PROP_THREAD_LEADER_RID) |
| { |
| if (try_spinel_datatype_unpack(Data, DataLength, SPINEL_DATATYPE_UINT8_S, (uint8_t*)OutBuffer)) |
| { |
| *OutBufferLength = sizeof(uint8_t); |
| status = STATUS_SUCCESS; |
| } |
| } |
| return status; |
| } |
| |
| _IRQL_requires_max_(PASSIVE_LEVEL) |
| NTSTATUS |
| otLwfIoCtl_otLeaderWeight( |
| _In_ PMS_FILTER pFilter, |
| _In_reads_bytes_(InBufferLength) |
| PUCHAR InBuffer, |
| _In_ ULONG InBufferLength, |
| _Out_writes_bytes_(*OutBufferLength) |
| PVOID OutBuffer, |
| _Inout_ PULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_INVALID_PARAMETER; |
| |
| UNREFERENCED_PARAMETER(InBuffer); |
| UNREFERENCED_PARAMETER(InBufferLength); |
| |
| if (*OutBufferLength >= sizeof(uint8_t)) |
| { |
| *(uint8_t*)OutBuffer = otThreadGetLeaderWeight(pFilter->otCtx); |
| *OutBufferLength = sizeof(uint8_t); |
| status = STATUS_SUCCESS; |
| } |
| else |
| { |
| *OutBufferLength = 0; |
| } |
| |
| return status; |
| } |
| |
| _IRQL_requires_max_(PASSIVE_LEVEL) |
| NTSTATUS |
| otLwfTunIoCtl_otLeaderWeight( |
| _In_ PMS_FILTER pFilter, |
| _In_ PIRP pIrp, |
| _In_reads_bytes_(InBufferLength) |
| PUCHAR InBuffer, |
| _In_ ULONG InBufferLength, |
| _In_ ULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_INVALID_PARAMETER; |
| |
| UNREFERENCED_PARAMETER(InBuffer); |
| UNREFERENCED_PARAMETER(InBufferLength); |
| |
| if (OutBufferLength >= sizeof(uint8_t)) |
| { |
| status = |
| otLwfTunSendCommandForIrp( |
| pFilter, |
| pIrp, |
| otLwfTunIoCtl_otLeaderWeight_Handler, |
| SPINEL_CMD_PROP_VALUE_GET, |
| SPINEL_PROP_THREAD_LEADER_WEIGHT, |
| 0, |
| NULL); |
| } |
| |
| return status; |
| } |
| |
| _IRQL_requires_max_(DISPATCH_LEVEL) |
| NTSTATUS |
| otLwfTunIoCtl_otLeaderWeight_Handler( |
| _In_ spinel_prop_key_t Key, |
| _In_reads_bytes_(DataLength) const uint8_t* Data, |
| _In_ spinel_size_t DataLength, |
| _Out_writes_bytes_(*OutBufferLength) |
| PVOID OutBuffer, |
| _Inout_ PULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_INVALID_PARAMETER; |
| if (Key == SPINEL_PROP_THREAD_LEADER_WEIGHT) |
| { |
| if (try_spinel_datatype_unpack(Data, DataLength, SPINEL_DATATYPE_UINT8_S, (uint8_t*)OutBuffer)) |
| { |
| *OutBufferLength = sizeof(uint8_t); |
| status = STATUS_SUCCESS; |
| } |
| } |
| return status; |
| } |
| |
| _IRQL_requires_max_(PASSIVE_LEVEL) |
| NTSTATUS |
| otLwfIoCtl_otNetworkDataVersion( |
| _In_ PMS_FILTER pFilter, |
| _In_reads_bytes_(InBufferLength) |
| PUCHAR InBuffer, |
| _In_ ULONG InBufferLength, |
| _Out_writes_bytes_(*OutBufferLength) |
| PVOID OutBuffer, |
| _Inout_ PULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_INVALID_PARAMETER; |
| |
| UNREFERENCED_PARAMETER(InBuffer); |
| UNREFERENCED_PARAMETER(InBufferLength); |
| |
| if (*OutBufferLength >= sizeof(uint8_t)) |
| { |
| *(uint8_t*)OutBuffer = otNetDataGetVersion(pFilter->otCtx); |
| *OutBufferLength = sizeof(uint8_t); |
| status = STATUS_SUCCESS; |
| } |
| else |
| { |
| *OutBufferLength = 0; |
| } |
| |
| return status; |
| } |
| |
| _IRQL_requires_max_(PASSIVE_LEVEL) |
| NTSTATUS |
| otLwfTunIoCtl_otNetworkDataVersion( |
| _In_ PMS_FILTER pFilter, |
| _In_ PIRP pIrp, |
| _In_reads_bytes_(InBufferLength) |
| PUCHAR InBuffer, |
| _In_ ULONG InBufferLength, |
| _In_ ULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_INVALID_PARAMETER; |
| |
| UNREFERENCED_PARAMETER(InBuffer); |
| UNREFERENCED_PARAMETER(InBufferLength); |
| |
| if (OutBufferLength >= sizeof(uint8_t)) |
| { |
| status = |
| otLwfTunSendCommandForIrp( |
| pFilter, |
| pIrp, |
| otLwfTunIoCtl_otNetworkDataVersion_Handler, |
| SPINEL_CMD_PROP_VALUE_GET, |
| SPINEL_PROP_THREAD_NETWORK_DATA_VERSION, |
| 0, |
| NULL); |
| } |
| |
| return status; |
| } |
| |
| _IRQL_requires_max_(DISPATCH_LEVEL) |
| NTSTATUS |
| otLwfTunIoCtl_otNetworkDataVersion_Handler( |
| _In_ spinel_prop_key_t Key, |
| _In_reads_bytes_(DataLength) const uint8_t* Data, |
| _In_ spinel_size_t DataLength, |
| _Out_writes_bytes_(*OutBufferLength) |
| PVOID OutBuffer, |
| _Inout_ PULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_INVALID_PARAMETER; |
| if (Key == SPINEL_PROP_THREAD_NETWORK_DATA_VERSION) |
| { |
| if (try_spinel_datatype_unpack(Data, DataLength, SPINEL_DATATYPE_UINT8_S, (uint8_t*)OutBuffer)) |
| { |
| *OutBufferLength = sizeof(uint8_t); |
| status = STATUS_SUCCESS; |
| } |
| } |
| return status; |
| } |
| |
| _IRQL_requires_max_(PASSIVE_LEVEL) |
| NTSTATUS |
| otLwfIoCtl_otPartitionId( |
| _In_ PMS_FILTER pFilter, |
| _In_reads_bytes_(InBufferLength) |
| PUCHAR InBuffer, |
| _In_ ULONG InBufferLength, |
| _Out_writes_bytes_(*OutBufferLength) |
| PVOID OutBuffer, |
| _Inout_ PULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_INVALID_PARAMETER; |
| |
| UNREFERENCED_PARAMETER(InBuffer); |
| UNREFERENCED_PARAMETER(InBufferLength); |
| |
| if (*OutBufferLength >= sizeof(uint32_t)) |
| { |
| *(uint32_t*)OutBuffer = otThreadGetPartitionId(pFilter->otCtx); |
| *OutBufferLength = sizeof(uint32_t); |
| status = STATUS_SUCCESS; |
| } |
| else |
| { |
| *OutBufferLength = 0; |
| } |
| |
| return status; |
| } |
| |
| _IRQL_requires_max_(PASSIVE_LEVEL) |
| NTSTATUS |
| otLwfTunIoCtl_otPartitionId( |
| _In_ PMS_FILTER pFilter, |
| _In_ PIRP pIrp, |
| _In_reads_bytes_(InBufferLength) |
| PUCHAR InBuffer, |
| _In_ ULONG InBufferLength, |
| _In_ ULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_INVALID_PARAMETER; |
| |
| UNREFERENCED_PARAMETER(InBuffer); |
| UNREFERENCED_PARAMETER(InBufferLength); |
| |
| if (OutBufferLength >= sizeof(uint32_t)) |
| { |
| status = |
| otLwfTunSendCommandForIrp( |
| pFilter, |
| pIrp, |
| otLwfTunIoCtl_otPartitionId_Handler, |
| SPINEL_CMD_PROP_VALUE_GET, |
| SPINEL_PROP_NET_PARTITION_ID, |
| 0, |
| NULL); |
| } |
| |
| return status; |
| } |
| |
| _IRQL_requires_max_(DISPATCH_LEVEL) |
| NTSTATUS |
| otLwfTunIoCtl_otPartitionId_Handler( |
| _In_ spinel_prop_key_t Key, |
| _In_reads_bytes_(DataLength) const uint8_t* Data, |
| _In_ spinel_size_t DataLength, |
| _Out_writes_bytes_(*OutBufferLength) |
| PVOID OutBuffer, |
| _Inout_ PULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_INVALID_PARAMETER; |
| if (Key == SPINEL_PROP_NET_PARTITION_ID) |
| { |
| if (try_spinel_datatype_unpack(Data, DataLength, SPINEL_DATATYPE_UINT32_S, (uint32_t*)OutBuffer)) |
| { |
| *OutBufferLength = sizeof(uint32_t); |
| status = STATUS_SUCCESS; |
| } |
| } |
| return status; |
| } |
| |
| _IRQL_requires_max_(PASSIVE_LEVEL) |
| NTSTATUS |
| otLwfIoCtl_otRloc16( |
| _In_ PMS_FILTER pFilter, |
| _In_reads_bytes_(InBufferLength) |
| PUCHAR InBuffer, |
| _In_ ULONG InBufferLength, |
| _Out_writes_bytes_(*OutBufferLength) |
| PVOID OutBuffer, |
| _Inout_ PULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_INVALID_PARAMETER; |
| |
| UNREFERENCED_PARAMETER(InBuffer); |
| UNREFERENCED_PARAMETER(InBufferLength); |
| |
| if (*OutBufferLength >= sizeof(uint16_t)) |
| { |
| *(uint16_t*)OutBuffer = otThreadGetRloc16(pFilter->otCtx); |
| *OutBufferLength = sizeof(uint16_t); |
| status = STATUS_SUCCESS; |
| } |
| else |
| { |
| *OutBufferLength = 0; |
| } |
| |
| return status; |
| } |
| |
| _IRQL_requires_max_(PASSIVE_LEVEL) |
| NTSTATUS |
| otLwfTunIoCtl_otRloc16( |
| _In_ PMS_FILTER pFilter, |
| _In_ PIRP pIrp, |
| _In_reads_bytes_(InBufferLength) |
| PUCHAR InBuffer, |
| _In_ ULONG InBufferLength, |
| _In_ ULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_INVALID_PARAMETER; |
| |
| UNREFERENCED_PARAMETER(InBuffer); |
| UNREFERENCED_PARAMETER(InBufferLength); |
| |
| if (OutBufferLength >= sizeof(uint16_t)) |
| { |
| status = |
| otLwfTunSendCommandForIrp( |
| pFilter, |
| pIrp, |
| otLwfTunIoCtl_otRloc16_Handler, |
| SPINEL_CMD_PROP_VALUE_GET, |
| SPINEL_PROP_THREAD_RLOC16, |
| 0, |
| NULL); |
| } |
| |
| return status; |
| } |
| |
| _IRQL_requires_max_(DISPATCH_LEVEL) |
| NTSTATUS |
| otLwfTunIoCtl_otRloc16_Handler( |
| _In_ spinel_prop_key_t Key, |
| _In_reads_bytes_(DataLength) const uint8_t* Data, |
| _In_ spinel_size_t DataLength, |
| _Out_writes_bytes_(*OutBufferLength) |
| PVOID OutBuffer, |
| _Inout_ PULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_INVALID_PARAMETER; |
| if (Key == SPINEL_PROP_THREAD_RLOC16) |
| { |
| if (try_spinel_datatype_unpack(Data, DataLength, SPINEL_DATATYPE_UINT16_S, (uint16_t*)OutBuffer)) |
| { |
| *OutBufferLength = sizeof(uint16_t); |
| status = STATUS_SUCCESS; |
| } |
| } |
| return status; |
| } |
| |
| _IRQL_requires_max_(PASSIVE_LEVEL) |
| NTSTATUS |
| otLwfIoCtl_otRouterIdSequence( |
| _In_ PMS_FILTER pFilter, |
| _In_reads_bytes_(InBufferLength) |
| PUCHAR InBuffer, |
| _In_ ULONG InBufferLength, |
| _Out_writes_bytes_(*OutBufferLength) |
| PVOID OutBuffer, |
| _Inout_ PULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_INVALID_PARAMETER; |
| |
| UNREFERENCED_PARAMETER(InBuffer); |
| UNREFERENCED_PARAMETER(InBufferLength); |
| |
| if (*OutBufferLength >= sizeof(uint8_t)) |
| { |
| *(uint8_t*)OutBuffer = otThreadGetRouterIdSequence(pFilter->otCtx); |
| *OutBufferLength = sizeof(uint8_t); |
| status = STATUS_SUCCESS; |
| } |
| else |
| { |
| *OutBufferLength = 0; |
| } |
| |
| return status; |
| } |
| |
| _IRQL_requires_max_(PASSIVE_LEVEL) |
| NTSTATUS |
| otLwfIoCtl_otRouterInfo( |
| _In_ PMS_FILTER pFilter, |
| _In_reads_bytes_(InBufferLength) |
| PUCHAR InBuffer, |
| _In_ ULONG InBufferLength, |
| _Out_writes_bytes_(*OutBufferLength) |
| PVOID OutBuffer, |
| _Inout_ PULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_INVALID_PARAMETER; |
| |
| if (InBufferLength >= sizeof(uint16_t) && |
| *OutBufferLength >= sizeof(otRouterInfo)) |
| { |
| status = ThreadErrorToNtstatus( |
| otThreadGetRouterInfo( |
| pFilter->otCtx, |
| *(uint16_t*)InBuffer, |
| (otRouterInfo*)OutBuffer) |
| ); |
| *OutBufferLength = sizeof(otRouterInfo); |
| } |
| else |
| { |
| *OutBufferLength = 0; |
| } |
| |
| return status; |
| } |
| |
| _IRQL_requires_max_(PASSIVE_LEVEL) |
| NTSTATUS |
| otLwfIoCtl_otStableNetworkDataVersion( |
| _In_ PMS_FILTER pFilter, |
| _In_reads_bytes_(InBufferLength) |
| PUCHAR InBuffer, |
| _In_ ULONG InBufferLength, |
| _Out_writes_bytes_(*OutBufferLength) |
| PVOID OutBuffer, |
| _Inout_ PULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_INVALID_PARAMETER; |
| |
| UNREFERENCED_PARAMETER(InBuffer); |
| UNREFERENCED_PARAMETER(InBufferLength); |
| |
| if (*OutBufferLength >= sizeof(uint8_t)) |
| { |
| *(uint8_t*)OutBuffer = otNetDataGetStableVersion(pFilter->otCtx); |
| *OutBufferLength = sizeof(uint8_t); |
| status = STATUS_SUCCESS; |
| } |
| else |
| { |
| *OutBufferLength = 0; |
| } |
| |
| return status; |
| } |
| |
| _IRQL_requires_max_(PASSIVE_LEVEL) |
| NTSTATUS |
| otLwfTunIoCtl_otStableNetworkDataVersion( |
| _In_ PMS_FILTER pFilter, |
| _In_ PIRP pIrp, |
| _In_reads_bytes_(InBufferLength) |
| PUCHAR InBuffer, |
| _In_ ULONG InBufferLength, |
| _In_ ULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_INVALID_PARAMETER; |
| |
| UNREFERENCED_PARAMETER(InBuffer); |
| UNREFERENCED_PARAMETER(InBufferLength); |
| |
| if (OutBufferLength >= sizeof(uint8_t)) |
| { |
| status = |
| otLwfTunSendCommandForIrp( |
| pFilter, |
| pIrp, |
| otLwfTunIoCtl_otStableNetworkDataVersion_Handler, |
| SPINEL_CMD_PROP_VALUE_GET, |
| SPINEL_PROP_THREAD_STABLE_NETWORK_DATA_VERSION, |
| 0, |
| NULL); |
| } |
| |
| return status; |
| } |
| |
| _IRQL_requires_max_(DISPATCH_LEVEL) |
| NTSTATUS |
| otLwfTunIoCtl_otStableNetworkDataVersion_Handler( |
| _In_ spinel_prop_key_t Key, |
| _In_reads_bytes_(DataLength) const uint8_t* Data, |
| _In_ spinel_size_t DataLength, |
| _Out_writes_bytes_(*OutBufferLength) |
| PVOID OutBuffer, |
| _Inout_ PULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_INVALID_PARAMETER; |
| if (Key == SPINEL_PROP_THREAD_STABLE_NETWORK_DATA_VERSION) |
| { |
| if (try_spinel_datatype_unpack(Data, DataLength, SPINEL_DATATYPE_UINT8_S, (uint8_t*)OutBuffer)) |
| { |
| *OutBufferLength = sizeof(uint8_t); |
| status = STATUS_SUCCESS; |
| } |
| } |
| return status; |
| } |
| |
| _IRQL_requires_max_(PASSIVE_LEVEL) |
| NTSTATUS |
| otLwfIoCtl_otMacBlacklistEnabled( |
| _In_ PMS_FILTER pFilter, |
| _In_reads_bytes_(InBufferLength) |
| PUCHAR InBuffer, |
| _In_ ULONG InBufferLength, |
| _Out_writes_bytes_(*OutBufferLength) |
| PVOID OutBuffer, |
| _Inout_ PULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_INVALID_PARAMETER; |
| |
| if (InBufferLength >= sizeof(BOOLEAN)) |
| { |
| BOOLEAN aEnabled = *(BOOLEAN*)InBuffer; |
| otLinkSetBlacklistEnabled(pFilter->otCtx, aEnabled); |
| status = STATUS_SUCCESS; |
| *OutBufferLength = 0; |
| } |
| else if (*OutBufferLength >= sizeof(BOOLEAN)) |
| { |
| *(BOOLEAN*)OutBuffer = otLinkIsBlacklistEnabled(pFilter->otCtx) ? TRUE : FALSE; |
| status = STATUS_SUCCESS; |
| *OutBufferLength = sizeof(BOOLEAN); |
| } |
| else |
| { |
| *OutBufferLength = 0; |
| } |
| |
| return status; |
| } |
| |
| _IRQL_requires_max_(PASSIVE_LEVEL) |
| NTSTATUS |
| otLwfIoCtl_otAddMacBlacklist( |
| _In_ PMS_FILTER pFilter, |
| _In_reads_bytes_(InBufferLength) |
| PUCHAR InBuffer, |
| _In_ ULONG InBufferLength, |
| _Out_writes_bytes_(*OutBufferLength) |
| PVOID OutBuffer, |
| _Inout_ PULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_INVALID_PARAMETER; |
| |
| UNREFERENCED_PARAMETER(OutBuffer); |
| *OutBufferLength = 0; |
| |
| if (InBufferLength >= sizeof(otExtAddress)) |
| { |
| status = ThreadErrorToNtstatus(otLinkAddBlacklist(pFilter->otCtx, (uint8_t*)InBuffer)); |
| } |
| |
| return status; |
| } |
| |
| _IRQL_requires_max_(PASSIVE_LEVEL) |
| NTSTATUS |
| otLwfIoCtl_otRemoveMacBlacklist( |
| _In_ PMS_FILTER pFilter, |
| _In_reads_bytes_(InBufferLength) |
| PUCHAR InBuffer, |
| _In_ ULONG InBufferLength, |
| _Out_writes_bytes_(*OutBufferLength) |
| PVOID OutBuffer, |
| _Inout_ PULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_INVALID_PARAMETER; |
| |
| UNREFERENCED_PARAMETER(OutBuffer); |
| *OutBufferLength = 0; |
| |
| if (InBufferLength >= sizeof(otExtAddress)) |
| { |
| otLinkRemoveBlacklist(pFilter->otCtx, (uint8_t*)InBuffer); |
| status = STATUS_SUCCESS; |
| } |
| |
| return status; |
| } |
| |
| _IRQL_requires_max_(PASSIVE_LEVEL) |
| NTSTATUS |
| otLwfIoCtl_otMacBlacklistEntry( |
| _In_ PMS_FILTER pFilter, |
| _In_reads_bytes_(InBufferLength) |
| PUCHAR InBuffer, |
| _In_ ULONG InBufferLength, |
| _Out_writes_bytes_(*OutBufferLength) |
| PVOID OutBuffer, |
| _Inout_ PULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_INVALID_PARAMETER; |
| |
| if (InBufferLength >= sizeof(uint8_t) && |
| *OutBufferLength >= sizeof(otMacBlacklistEntry)) |
| { |
| status = ThreadErrorToNtstatus( |
| otLinkGetBlacklistEntry( |
| pFilter->otCtx, |
| *(uint8_t*)InBuffer, |
| (otMacBlacklistEntry*)OutBuffer) |
| ); |
| *OutBufferLength = sizeof(otMacBlacklistEntry); |
| } |
| else |
| { |
| *OutBufferLength = 0; |
| } |
| |
| return status; |
| } |
| |
| _IRQL_requires_max_(PASSIVE_LEVEL) |
| NTSTATUS |
| otLwfIoCtl_otClearMacBlacklist( |
| _In_ PMS_FILTER pFilter, |
| _In_reads_bytes_(InBufferLength) |
| PUCHAR InBuffer, |
| _In_ ULONG InBufferLength, |
| _Out_writes_bytes_(*OutBufferLength) |
| PVOID OutBuffer, |
| _Inout_ PULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_SUCCESS; |
| |
| UNREFERENCED_PARAMETER(InBuffer); |
| UNREFERENCED_PARAMETER(InBufferLength); |
| UNREFERENCED_PARAMETER(OutBuffer); |
| *OutBufferLength = 0; |
| |
| otLinkClearBlacklist(pFilter->otCtx); |
| |
| return status; |
| } |
| |
| _IRQL_requires_max_(PASSIVE_LEVEL) |
| NTSTATUS |
| otLwfIoCtl_otMaxTransmitPower( |
| _In_ PMS_FILTER pFilter, |
| _In_reads_bytes_(InBufferLength) |
| PUCHAR InBuffer, |
| _In_ ULONG InBufferLength, |
| _Out_writes_bytes_(*OutBufferLength) |
| PVOID OutBuffer, |
| _Inout_ PULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_INVALID_PARAMETER; |
| |
| if (InBufferLength >= sizeof(int8_t)) |
| { |
| otLinkSetMaxTransmitPower(pFilter->otCtx, *(int8_t*)InBuffer); |
| status = STATUS_SUCCESS; |
| *OutBufferLength = 0; |
| } |
| else if (*OutBufferLength >= sizeof(int8_t)) |
| { |
| *(int8_t*)OutBuffer = otLinkGetMaxTransmitPower(pFilter->otCtx); |
| *OutBufferLength = sizeof(int8_t); |
| status = STATUS_SUCCESS; |
| } |
| else |
| { |
| *OutBufferLength = 0; |
| } |
| |
| return status; |
| } |
| |
| _IRQL_requires_max_(PASSIVE_LEVEL) |
| NTSTATUS |
| otLwfIoCtl_otNextOnMeshPrefix( |
| _In_ PMS_FILTER pFilter, |
| _In_reads_bytes_(InBufferLength) |
| PUCHAR InBuffer, |
| _In_ ULONG InBufferLength, |
| _Out_writes_bytes_(*OutBufferLength) |
| PVOID OutBuffer, |
| _Inout_ PULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_INVALID_PARAMETER; |
| |
| if (InBufferLength >= sizeof(BOOLEAN) + sizeof(uint8_t) && |
| *OutBufferLength >= sizeof(uint8_t) + sizeof(otBorderRouterConfig)) |
| { |
| BOOLEAN aLocal = *(BOOLEAN*)InBuffer; |
| uint8_t aIterator = *(uint8_t*)(InBuffer + sizeof(BOOLEAN)); |
| otBorderRouterConfig* aConfig = (otBorderRouterConfig*)((PUCHAR)OutBuffer + sizeof(uint8_t)); |
| if (aLocal) |
| { |
| status = ThreadErrorToNtstatus( |
| otBorderRouterGetNextOnMeshPrefix( |
| pFilter->otCtx, |
| &aIterator, |
| aConfig) |
| ); |
| } |
| else |
| { |
| status = ThreadErrorToNtstatus( |
| otNetDataGetNextOnMeshPrefix( |
| pFilter->otCtx, |
| &aIterator, |
| aConfig) |
| ); |
| } |
| *OutBufferLength = sizeof(uint8_t) + sizeof(otBorderRouterConfig); |
| if (status == STATUS_SUCCESS) |
| { |
| *(uint8_t*)OutBuffer = aIterator; |
| } |
| } |
| else |
| { |
| *OutBufferLength = 0; |
| } |
| |
| return status; |
| } |
| |
| _IRQL_requires_max_(PASSIVE_LEVEL) |
| NTSTATUS |
| otLwfIoCtl_otPollPeriod( |
| _In_ PMS_FILTER pFilter, |
| _In_reads_bytes_(InBufferLength) |
| PUCHAR InBuffer, |
| _In_ ULONG InBufferLength, |
| _Out_writes_bytes_(*OutBufferLength) |
| PVOID OutBuffer, |
| _Inout_ PULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_INVALID_PARAMETER; |
| |
| if (InBufferLength >= sizeof(uint32_t)) |
| { |
| otLinkSetPollPeriod(pFilter->otCtx, *(uint32_t*)InBuffer); |
| status = STATUS_SUCCESS; |
| *OutBufferLength = 0; |
| } |
| else if (*OutBufferLength >= sizeof(uint32_t)) |
| { |
| *(uint32_t*)OutBuffer = otLinkGetPollPeriod(pFilter->otCtx); |
| *OutBufferLength = sizeof(uint32_t); |
| status = STATUS_SUCCESS; |
| } |
| else |
| { |
| *OutBufferLength = 0; |
| } |
| |
| return status; |
| } |
| |
| _IRQL_requires_max_(PASSIVE_LEVEL) |
| NTSTATUS |
| otLwfIoCtl_otLocalLeaderPartitionId( |
| _In_ PMS_FILTER pFilter, |
| _In_reads_bytes_(InBufferLength) |
| PUCHAR InBuffer, |
| _In_ ULONG InBufferLength, |
| _Out_writes_bytes_(*OutBufferLength) |
| PVOID OutBuffer, |
| _Inout_ PULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_INVALID_PARAMETER; |
| |
| if (InBufferLength >= sizeof(uint32_t)) |
| { |
| otThreadSetLocalLeaderPartitionId(pFilter->otCtx, *(uint32_t*)InBuffer); |
| status = STATUS_SUCCESS; |
| *OutBufferLength = 0; |
| } |
| else if (*OutBufferLength >= sizeof(uint32_t)) |
| { |
| *(uint32_t*)OutBuffer = otThreadGetLocalLeaderPartitionId(pFilter->otCtx); |
| *OutBufferLength = sizeof(uint32_t); |
| status = STATUS_SUCCESS; |
| } |
| else |
| { |
| *OutBufferLength = 0; |
| } |
| |
| return status; |
| } |
| |
| _IRQL_requires_max_(PASSIVE_LEVEL) |
| NTSTATUS |
| otLwfIoCtl_otAssignLinkQuality( |
| _In_ PMS_FILTER pFilter, |
| _In_reads_bytes_(InBufferLength) |
| PUCHAR InBuffer, |
| _In_ ULONG InBufferLength, |
| _Out_writes_bytes_(*OutBufferLength) |
| PVOID OutBuffer, |
| _Inout_ PULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_INVALID_PARAMETER; |
| |
| if (InBufferLength >= sizeof(otExtAddress) + sizeof(uint8_t)) |
| { |
| otLinkSetAssignLinkQuality( |
| pFilter->otCtx, |
| (uint8_t*)InBuffer, |
| *(uint8_t*)(InBuffer + sizeof(otExtAddress))); |
| status = STATUS_SUCCESS; |
| *OutBufferLength = 0; |
| } |
| else if (InBufferLength >= sizeof(otExtAddress) && |
| *OutBufferLength >= sizeof(uint8_t)) |
| { |
| status = ThreadErrorToNtstatus( |
| otLinkGetAssignLinkQuality( |
| pFilter->otCtx, |
| (uint8_t*)InBuffer, |
| (uint8_t*)OutBuffer) |
| ); |
| *OutBufferLength = sizeof(uint32_t); |
| } |
| else |
| { |
| *OutBufferLength = 0; |
| } |
| |
| return status; |
| } |
| |
| _IRQL_requires_max_(PASSIVE_LEVEL) |
| NTSTATUS |
| otLwfIoCtl_otPlatformReset( |
| _In_ PMS_FILTER pFilter, |
| _In_reads_bytes_(InBufferLength) |
| PUCHAR InBuffer, |
| _In_ ULONG InBufferLength, |
| _Out_writes_bytes_(*OutBufferLength) |
| PVOID OutBuffer, |
| _Inout_ PULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_SUCCESS; |
| |
| UNREFERENCED_PARAMETER(InBuffer); |
| UNREFERENCED_PARAMETER(InBufferLength); |
| UNREFERENCED_PARAMETER(OutBuffer); |
| *OutBufferLength = 0; |
| |
| otInstanceReset(pFilter->otCtx); |
| |
| return status; |
| } |
| |
| _IRQL_requires_max_(PASSIVE_LEVEL) |
| NTSTATUS |
| otLwfIoCtl_otFactoryReset( |
| _In_ PMS_FILTER pFilter, |
| _In_reads_bytes_(InBufferLength) |
| PUCHAR InBuffer, |
| _In_ ULONG InBufferLength, |
| _Out_writes_bytes_(*OutBufferLength) |
| PVOID OutBuffer, |
| _Inout_ PULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_SUCCESS; |
| |
| UNREFERENCED_PARAMETER(InBuffer); |
| UNREFERENCED_PARAMETER(InBufferLength); |
| UNREFERENCED_PARAMETER(OutBuffer); |
| *OutBufferLength = 0; |
| |
| otInstanceFactoryReset(pFilter->otCtx); |
| |
| return status; |
| } |
| |
| _IRQL_requires_max_(PASSIVE_LEVEL) |
| NTSTATUS |
| otLwfTunIoCtl_otPlatformReset( |
| _In_ PMS_FILTER pFilter, |
| _In_ PIRP pIrp, |
| _In_reads_bytes_(InBufferLength) |
| PUCHAR InBuffer, |
| _In_ ULONG InBufferLength, |
| _In_ ULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_INVALID_PARAMETER; |
| |
| UNREFERENCED_PARAMETER(InBuffer); |
| UNREFERENCED_PARAMETER(InBufferLength); |
| UNREFERENCED_PARAMETER(OutBufferLength); |
| |
| status = |
| otLwfTunSendCommandForIrp( |
| pFilter, |
| pIrp, |
| NULL, |
| SPINEL_CMD_RESET, |
| 0, |
| 0, |
| NULL); |
| |
| return status; |
| } |
| |
| _IRQL_requires_max_(PASSIVE_LEVEL) |
| NTSTATUS |
| otLwfIoCtl_otParentInfo( |
| _In_ PMS_FILTER pFilter, |
| _In_reads_bytes_(InBufferLength) |
| PUCHAR InBuffer, |
| _In_ ULONG InBufferLength, |
| _Out_writes_bytes_(*OutBufferLength) |
| PVOID OutBuffer, |
| _Inout_ PULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_INVALID_PARAMETER; |
| |
| UNREFERENCED_PARAMETER(InBuffer); |
| UNREFERENCED_PARAMETER(InBufferLength); |
| |
| static_assert(sizeof(otRouterInfo) == 20, "The size of otRouterInfo should be 20 bytes"); |
| if (*OutBufferLength >= sizeof(otRouterInfo)) |
| { |
| status = ThreadErrorToNtstatus(otThreadGetParentInfo(pFilter->otCtx, (otRouterInfo*)OutBuffer)); |
| *OutBufferLength = sizeof(otRouterInfo); |
| } |
| else |
| { |
| *OutBufferLength = 0; |
| } |
| |
| return status; |
| } |
| |
| _IRQL_requires_max_(PASSIVE_LEVEL) |
| NTSTATUS |
| otLwfTunIoCtl_otParentInfo( |
| _In_ PMS_FILTER pFilter, |
| _In_ PIRP pIrp, |
| _In_reads_bytes_(InBufferLength) |
| PUCHAR InBuffer, |
| _In_ ULONG InBufferLength, |
| _In_ ULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_INVALID_PARAMETER; |
| |
| UNREFERENCED_PARAMETER(InBuffer); |
| UNREFERENCED_PARAMETER(InBufferLength); |
| |
| if (OutBufferLength >= sizeof(otRouterInfo)) |
| { |
| status = |
| otLwfTunSendCommandForIrp( |
| pFilter, |
| pIrp, |
| otLwfTunIoCtl_otParentInfo_Handler, |
| SPINEL_CMD_PROP_VALUE_GET, |
| SPINEL_PROP_THREAD_PARENT, |
| 0, |
| NULL); |
| } |
| |
| return status; |
| } |
| |
| _IRQL_requires_max_(DISPATCH_LEVEL) |
| NTSTATUS |
| otLwfTunIoCtl_otParentInfo_Handler( |
| _In_ spinel_prop_key_t Key, |
| _In_reads_bytes_(DataLength) const uint8_t* Data, |
| _In_ spinel_size_t DataLength, |
| _Out_writes_bytes_(*OutBufferLength) |
| PVOID OutBuffer, |
| _Inout_ PULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_INVALID_PARAMETER; |
| if (Key == SPINEL_PROP_THREAD_PARENT) |
| { |
| otRouterInfo* aRouterInfo = (otRouterInfo*)OutBuffer; |
| RtlZeroMemory(aRouterInfo, sizeof(otRouterInfo)); |
| if (try_spinel_datatype_unpack(Data, DataLength, "ES", &aRouterInfo->mExtAddress.m8, &aRouterInfo->mRloc16)) |
| { |
| *OutBufferLength = sizeof(uint8_t); |
| status = STATUS_SUCCESS; |
| } |
| } |
| return status; |
| } |
| |
| _IRQL_requires_max_(PASSIVE_LEVEL) |
| NTSTATUS |
| otLwfIoCtl_otSingleton( |
| _In_ PMS_FILTER pFilter, |
| _In_reads_bytes_(InBufferLength) |
| PUCHAR InBuffer, |
| _In_ ULONG InBufferLength, |
| _Out_writes_bytes_(*OutBufferLength) |
| PVOID OutBuffer, |
| _Inout_ PULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_INVALID_PARAMETER; |
| |
| UNREFERENCED_PARAMETER(InBuffer); |
| UNREFERENCED_PARAMETER(InBufferLength); |
| |
| if (*OutBufferLength >= sizeof(BOOLEAN)) |
| { |
| *(BOOLEAN*)OutBuffer = otThreadIsSingleton(pFilter->otCtx) ? TRUE : FALSE; |
| *OutBufferLength = sizeof(BOOLEAN); |
| status = STATUS_SUCCESS; |
| } |
| else |
| { |
| *OutBufferLength = 0; |
| } |
| |
| return status; |
| } |
| |
| _IRQL_requires_max_(PASSIVE_LEVEL) |
| NTSTATUS |
| otLwfIoCtl_otMacCounters( |
| _In_ PMS_FILTER pFilter, |
| _In_reads_bytes_(InBufferLength) |
| PUCHAR InBuffer, |
| _In_ ULONG InBufferLength, |
| _Out_writes_bytes_(*OutBufferLength) |
| PVOID OutBuffer, |
| _Inout_ PULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_INVALID_PARAMETER; |
| |
| UNREFERENCED_PARAMETER(InBuffer); |
| UNREFERENCED_PARAMETER(InBufferLength); |
| |
| if (*OutBufferLength >= sizeof(otMacCounters)) |
| { |
| memcpy_s(OutBuffer, *OutBufferLength, otLinkGetCounters(pFilter->otCtx), sizeof(otMacCounters)); |
| *OutBufferLength = sizeof(otMacCounters); |
| status = STATUS_SUCCESS; |
| } |
| else |
| { |
| *OutBufferLength = 0; |
| } |
| |
| return status; |
| } |
| |
| _IRQL_requires_max_(PASSIVE_LEVEL) |
| NTSTATUS |
| otLwfIoCtl_otMaxChildren( |
| _In_ PMS_FILTER pFilter, |
| _In_reads_bytes_(InBufferLength) |
| PUCHAR InBuffer, |
| _In_ ULONG InBufferLength, |
| _Out_writes_bytes_(*OutBufferLength) |
| PVOID OutBuffer, |
| _Inout_ PULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_INVALID_PARAMETER; |
| |
| if (InBufferLength >= sizeof(uint8_t)) |
| { |
| otThreadSetMaxAllowedChildren(pFilter->otCtx, *(uint8_t*)InBuffer); |
| status = STATUS_SUCCESS; |
| *OutBufferLength = 0; |
| } |
| else if (*OutBufferLength >= sizeof(uint8_t)) |
| { |
| *(uint8_t*)OutBuffer = otThreadGetMaxAllowedChildren(pFilter->otCtx); |
| *OutBufferLength = sizeof(uint8_t); |
| status = STATUS_SUCCESS; |
| } |
| else |
| { |
| *OutBufferLength = 0; |
| } |
| |
| return status; |
| } |
| |
| _IRQL_requires_max_(PASSIVE_LEVEL) |
| NTSTATUS |
| otLwfTunIoCtl_otMaxChildren( |
| _In_ PMS_FILTER pFilter, |
| _In_ PIRP pIrp, |
| _In_reads_bytes_(InBufferLength) |
| PUCHAR InBuffer, |
| _In_ ULONG InBufferLength, |
| _In_ ULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_INVALID_PARAMETER; |
| |
| if (InBufferLength >= sizeof(uint8_t)) |
| { |
| status = |
| otLwfTunSendCommandForIrp( |
| pFilter, |
| pIrp, |
| NULL, |
| SPINEL_CMD_PROP_VALUE_SET, |
| SPINEL_PROP_THREAD_CHILD_COUNT_MAX, |
| sizeof(uint8_t), |
| SPINEL_DATATYPE_UINT8_S, |
| *(uint8_t*)InBuffer); |
| } |
| else if (OutBufferLength >= sizeof(uint8_t)) |
| { |
| status = |
| otLwfTunSendCommandForIrp( |
| pFilter, |
| pIrp, |
| otLwfTunIoCtl_otMaxChildren_Handler, |
| SPINEL_CMD_PROP_VALUE_GET, |
| SPINEL_PROP_THREAD_CHILD_COUNT_MAX, |
| 0, |
| NULL); |
| } |
| |
| return status; |
| } |
| |
| _IRQL_requires_max_(DISPATCH_LEVEL) |
| NTSTATUS |
| otLwfTunIoCtl_otMaxChildren_Handler( |
| _In_ spinel_prop_key_t Key, |
| _In_reads_bytes_(DataLength) const uint8_t* Data, |
| _In_ spinel_size_t DataLength, |
| _Out_writes_bytes_(*OutBufferLength) |
| PVOID OutBuffer, |
| _Inout_ PULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_INVALID_PARAMETER; |
| if (Key == SPINEL_PROP_THREAD_CHILD_COUNT_MAX) |
| { |
| if (try_spinel_datatype_unpack(Data, DataLength, SPINEL_DATATYPE_UINT8_S, (uint8_t*)OutBuffer)) |
| { |
| *OutBufferLength = sizeof(uint8_t); |
| status = STATUS_SUCCESS; |
| } |
| } |
| return status; |
| } |
| |
| _IRQL_requires_max_(PASSIVE_LEVEL) |
| NTSTATUS |
| otLwfIoCtl_otCommissionerStart( |
| _In_ PMS_FILTER pFilter, |
| _In_reads_bytes_(InBufferLength) |
| PUCHAR InBuffer, |
| _In_ ULONG InBufferLength, |
| _Out_writes_bytes_(*OutBufferLength) |
| PVOID OutBuffer, |
| _Inout_ PULONG OutBufferLength |
| ) |
| { |
| UNREFERENCED_PARAMETER(InBuffer); |
| UNREFERENCED_PARAMETER(InBufferLength); |
| UNREFERENCED_PARAMETER(OutBuffer); |
| *OutBufferLength = 0; |
| |
| return ThreadErrorToNtstatus(otCommissionerStart(pFilter->otCtx)); |
| } |
| |
| _IRQL_requires_max_(PASSIVE_LEVEL) |
| NTSTATUS |
| otLwfIoCtl_otCommissionerStop( |
| _In_ PMS_FILTER pFilter, |
| _In_reads_bytes_(InBufferLength) |
| PUCHAR InBuffer, |
| _In_ ULONG InBufferLength, |
| _Out_writes_bytes_(*OutBufferLength) |
| PVOID OutBuffer, |
| _Inout_ PULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_SUCCESS; |
| |
| UNREFERENCED_PARAMETER(InBuffer); |
| UNREFERENCED_PARAMETER(InBufferLength); |
| UNREFERENCED_PARAMETER(OutBuffer); |
| *OutBufferLength = 0; |
| |
| status = ThreadErrorToNtstatus(otCommissionerStop(pFilter->otCtx)); |
| |
| return status; |
| } |
| |
| _IRQL_requires_max_(PASSIVE_LEVEL) |
| NTSTATUS |
| otLwfIoCtl_otJoinerStart( |
| _In_ PMS_FILTER pFilter, |
| _In_reads_bytes_(InBufferLength) |
| PUCHAR InBuffer, |
| _In_ ULONG InBufferLength, |
| _Out_writes_bytes_(*OutBufferLength) |
| PVOID OutBuffer, |
| _Inout_ PULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_SUCCESS; |
| |
| UNREFERENCED_PARAMETER(OutBuffer); |
| *OutBufferLength = 0; |
| |
| if (InBufferLength >= sizeof(otCommissionConfig)) |
| { |
| otCommissionConfig *aConfig = (otCommissionConfig*)InBuffer; |
| |
| #define IsNotNullTerminated(buf) (strnlen(buf, sizeof(buf)) == sizeof(buf)) |
| |
| if (IsNotNullTerminated(aConfig->PSKd) || |
| IsNotNullTerminated(aConfig->ProvisioningUrl) || |
| IsNotNullTerminated(aConfig->VendorName) || |
| IsNotNullTerminated(aConfig->VendorModel) || |
| IsNotNullTerminated(aConfig->VendorSwVersion) || |
| IsNotNullTerminated(aConfig->VendorData)) |
| { |
| status = STATUS_INVALID_PARAMETER; |
| } |
| else |
| { |
| strcpy_s(pFilter->otVendorName, sizeof(pFilter->otVendorName), aConfig->VendorName); |
| strcpy_s(pFilter->otVendorModel, sizeof(pFilter->otVendorModel), aConfig->VendorModel); |
| strcpy_s(pFilter->otVendorSwVersion, sizeof(pFilter->otVendorSwVersion), aConfig->VendorSwVersion); |
| strcpy_s(pFilter->otVendorData, sizeof(pFilter->otVendorData), aConfig->VendorData); |
| |
| status = ThreadErrorToNtstatus( |
| otJoinerStart( |
| pFilter->otCtx, |
| aConfig->PSKd, |
| aConfig->ProvisioningUrl, |
| pFilter->otVendorName, |
| pFilter->otVendorModel, |
| pFilter->otVendorSwVersion, |
| pFilter->otVendorData[0] == '\0' ? NULL : pFilter->otVendorData, |
| otLwfJoinerCallback, |
| pFilter) |
| ); |
| } |
| } |
| |
| return status; |
| } |
| |
| _IRQL_requires_max_(PASSIVE_LEVEL) |
| NTSTATUS |
| otLwfIoCtl_otJoinerStop( |
| _In_ PMS_FILTER pFilter, |
| _In_reads_bytes_(InBufferLength) |
| PUCHAR InBuffer, |
| _In_ ULONG InBufferLength, |
| _Out_writes_bytes_(*OutBufferLength) |
| PVOID OutBuffer, |
| _Inout_ PULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_SUCCESS; |
| |
| UNREFERENCED_PARAMETER(InBuffer); |
| UNREFERENCED_PARAMETER(InBufferLength); |
| UNREFERENCED_PARAMETER(OutBuffer); |
| *OutBufferLength = 0; |
| |
| status = ThreadErrorToNtstatus(otJoinerStop(pFilter->otCtx)); |
| |
| return status; |
| } |
| |
| _IRQL_requires_max_(PASSIVE_LEVEL) |
| NTSTATUS |
| otLwfIoCtl_otCommissionerPanIdQuery( |
| _In_ PMS_FILTER pFilter, |
| _In_reads_bytes_(InBufferLength) |
| PUCHAR InBuffer, |
| _In_ ULONG InBufferLength, |
| _Out_writes_bytes_(*OutBufferLength) |
| PVOID OutBuffer, |
| _Inout_ PULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_INVALID_PARAMETER; |
| |
| *OutBufferLength = 0; |
| UNREFERENCED_PARAMETER(OutBuffer); |
| |
| if (InBufferLength >= sizeof(uint16_t) + sizeof(uint32_t) + sizeof(otIp6Address)) |
| { |
| uint16_t aPanId = *(uint16_t*)InBuffer; |
| uint32_t aChannelMask = *(uint32_t*)(InBuffer + sizeof(uint16_t)); |
| const otIp6Address *aAddress = (otIp6Address*)(InBuffer + sizeof(uint16_t) + sizeof(uint32_t)); |
| |
| status = ThreadErrorToNtstatus( |
| otCommissionerPanIdQuery( |
| pFilter->otCtx, |
| aPanId, |
| aChannelMask, |
| aAddress, |
| otLwfCommissionerPanIdConflictCallback, |
| pFilter) |
| ); |
| } |
| |
| return status; |
| } |
| |
| _IRQL_requires_max_(PASSIVE_LEVEL) |
| NTSTATUS |
| otLwfIoCtl_otCommissionerEnergyScan( |
| _In_ PMS_FILTER pFilter, |
| _In_reads_bytes_(InBufferLength) |
| PUCHAR InBuffer, |
| _In_ ULONG InBufferLength, |
| _Out_writes_bytes_(*OutBufferLength) |
| PVOID OutBuffer, |
| _Inout_ PULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_INVALID_PARAMETER; |
| |
| *OutBufferLength = 0; |
| UNREFERENCED_PARAMETER(OutBuffer); |
| |
| if (InBufferLength >= sizeof(uint32_t) + sizeof(uint8_t) + sizeof(uint16_t) + sizeof(uint16_t) + sizeof(otIp6Address)) |
| { |
| uint32_t aChannelMask = *(uint32_t*)InBuffer; |
| uint8_t aCount = *(uint8_t*)(InBuffer + sizeof(uint32_t)); |
| uint16_t aPeriod = *(uint16_t*)(InBuffer + sizeof(uint32_t) + sizeof(uint8_t)); |
| uint16_t aScanDuration = *(uint16_t*)(InBuffer + sizeof(uint32_t) + sizeof(uint8_t) + sizeof(uint16_t)); |
| const otIp6Address *aAddress = (otIp6Address*)(InBuffer + sizeof(uint32_t) + sizeof(uint8_t) + sizeof(uint16_t) + sizeof(uint16_t)); |
| |
| status = ThreadErrorToNtstatus( |
| otCommissionerEnergyScan( |
| pFilter->otCtx, |
| aChannelMask, |
| aCount, |
| aPeriod, |
| aScanDuration, |
| aAddress, |
| otLwfCommissionerEnergyReportCallback, |
| pFilter) |
| ); |
| } |
| |
| return status; |
| } |
| |
| _IRQL_requires_max_(PASSIVE_LEVEL) |
| NTSTATUS |
| otLwfIoCtl_otRouterSelectionJitter( |
| _In_ PMS_FILTER pFilter, |
| _In_reads_bytes_(InBufferLength) |
| PUCHAR InBuffer, |
| _In_ ULONG InBufferLength, |
| _Out_writes_bytes_(*OutBufferLength) |
| PVOID OutBuffer, |
| _Inout_ PULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_INVALID_PARAMETER; |
| |
| if (InBufferLength >= sizeof(uint8_t)) |
| { |
| otThreadSetRouterSelectionJitter(pFilter->otCtx, *(uint8_t*)InBuffer); |
| status = STATUS_SUCCESS; |
| *OutBufferLength = 0; |
| } |
| else if (*OutBufferLength >= sizeof(uint8_t)) |
| { |
| *(uint8_t*)OutBuffer = otThreadGetRouterSelectionJitter(pFilter->otCtx); |
| status = STATUS_SUCCESS; |
| *OutBufferLength = sizeof(uint8_t); |
| } |
| else |
| { |
| *OutBufferLength = 0; |
| } |
| |
| return status; |
| } |
| |
| _IRQL_requires_max_(PASSIVE_LEVEL) |
| NTSTATUS |
| otLwfTunIoCtl_otRouterSelectionJitter( |
| _In_ PMS_FILTER pFilter, |
| _In_ PIRP pIrp, |
| _In_reads_bytes_(InBufferLength) |
| PUCHAR InBuffer, |
| _In_ ULONG InBufferLength, |
| _In_ ULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_INVALID_PARAMETER; |
| |
| if (InBufferLength >= sizeof(uint8_t)) |
| { |
| status = |
| otLwfTunSendCommandForIrp( |
| pFilter, |
| pIrp, |
| NULL, |
| SPINEL_CMD_PROP_VALUE_SET, |
| SPINEL_PROP_THREAD_ROUTER_SELECTION_JITTER, |
| sizeof(uint8_t), |
| SPINEL_DATATYPE_UINT8_S, |
| *(uint8_t*)InBuffer); |
| } |
| else if (OutBufferLength >= sizeof(uint8_t)) |
| { |
| status = |
| otLwfTunSendCommandForIrp( |
| pFilter, |
| pIrp, |
| otLwfTunIoCtl_otRouterSelectionJitter_Handler, |
| SPINEL_CMD_PROP_VALUE_GET, |
| SPINEL_PROP_THREAD_ROUTER_SELECTION_JITTER, |
| 0, |
| NULL); |
| } |
| |
| return status; |
| } |
| |
| _IRQL_requires_max_(DISPATCH_LEVEL) |
| NTSTATUS |
| otLwfTunIoCtl_otRouterSelectionJitter_Handler( |
| _In_ spinel_prop_key_t Key, |
| _In_reads_bytes_(DataLength) const uint8_t* Data, |
| _In_ spinel_size_t DataLength, |
| _Out_writes_bytes_(*OutBufferLength) |
| PVOID OutBuffer, |
| _Inout_ PULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_INVALID_PARAMETER; |
| if (Key == SPINEL_PROP_THREAD_ROUTER_SELECTION_JITTER) |
| { |
| if (try_spinel_datatype_unpack(Data, DataLength, SPINEL_DATATYPE_UINT8_S, (uint8_t*)OutBuffer)) |
| { |
| *OutBufferLength = sizeof(uint8_t); |
| status = STATUS_SUCCESS; |
| } |
| } |
| return status; |
| } |
| |
| _IRQL_requires_max_(PASSIVE_LEVEL) |
| NTSTATUS |
| otLwfIoCtl_otJoinerUdpPort( |
| _In_ PMS_FILTER pFilter, |
| _In_reads_bytes_(InBufferLength) |
| PUCHAR InBuffer, |
| _In_ ULONG InBufferLength, |
| _Out_writes_bytes_(*OutBufferLength) |
| PVOID OutBuffer, |
| _Inout_ PULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_INVALID_PARAMETER; |
| |
| if (InBufferLength >= sizeof(uint16_t)) |
| { |
| otThreadSetJoinerUdpPort(pFilter->otCtx, *(uint16_t*)InBuffer); |
| status = STATUS_SUCCESS; |
| *OutBufferLength = 0; |
| } |
| else if (*OutBufferLength >= sizeof(uint16_t)) |
| { |
| *(uint16_t*)OutBuffer = otThreadGetJoinerUdpPort(pFilter->otCtx); |
| status = STATUS_SUCCESS; |
| *OutBufferLength = sizeof(uint16_t); |
| } |
| else |
| { |
| *OutBufferLength = 0; |
| } |
| |
| return status; |
| } |
| |
| _IRQL_requires_max_(PASSIVE_LEVEL) |
| NTSTATUS |
| otLwfIoCtl_otSendDiagnosticGet( |
| _In_ PMS_FILTER pFilter, |
| _In_reads_bytes_(InBufferLength) |
| PUCHAR InBuffer, |
| _In_ ULONG InBufferLength, |
| _Out_writes_bytes_(*OutBufferLength) |
| PVOID OutBuffer, |
| _Inout_ PULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_INVALID_PARAMETER; |
| |
| *OutBufferLength = 0; |
| UNREFERENCED_PARAMETER(OutBuffer); |
| |
| if (InBufferLength >= sizeof(otIp6Address) + sizeof(uint8_t)) |
| { |
| const otIp6Address *aAddress = (otIp6Address*)InBuffer; |
| uint8_t aCount = *(uint8_t*)(InBuffer + sizeof(otIp6Address)); |
| PUCHAR aTlvTypes = InBuffer + sizeof(otIp6Address) + sizeof(uint8_t); |
| |
| if (InBufferLength >= sizeof(otIp6Address) + sizeof(uint8_t) + aCount) |
| { |
| status = ThreadErrorToNtstatus( |
| otThreadSendDiagnosticGet( |
| pFilter->otCtx, |
| aAddress, |
| aTlvTypes, |
| aCount) |
| ); |
| } |
| } |
| |
| return status; |
| } |
| |
| _IRQL_requires_max_(PASSIVE_LEVEL) |
| NTSTATUS |
| otLwfIoCtl_otSendDiagnosticReset( |
| _In_ PMS_FILTER pFilter, |
| _In_reads_bytes_(InBufferLength) |
| PUCHAR InBuffer, |
| _In_ ULONG InBufferLength, |
| _Out_writes_bytes_(*OutBufferLength) |
| PVOID OutBuffer, |
| _Inout_ PULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_INVALID_PARAMETER; |
| |
| *OutBufferLength = 0; |
| UNREFERENCED_PARAMETER(OutBuffer); |
| |
| if (InBufferLength >= sizeof(otIp6Address) + sizeof(uint8_t)) |
| { |
| const otIp6Address *aAddress = (otIp6Address*)InBuffer; |
| uint8_t aCount = *(uint8_t*)(InBuffer + sizeof(otIp6Address)); |
| PUCHAR aTlvTypes = InBuffer + sizeof(otIp6Address) + sizeof(uint8_t); |
| |
| if (InBufferLength >= sizeof(otIp6Address) + sizeof(uint8_t) + aCount) |
| { |
| status = ThreadErrorToNtstatus( |
| otThreadSendDiagnosticReset( |
| pFilter->otCtx, |
| aAddress, |
| aTlvTypes, |
| aCount) |
| ); |
| } |
| } |
| |
| return status; |
| } |
| |
| _IRQL_requires_max_(PASSIVE_LEVEL) |
| NTSTATUS |
| otLwfIoCtl_otCommissionerAddJoiner( |
| _In_ PMS_FILTER pFilter, |
| _In_reads_bytes_(InBufferLength) |
| PUCHAR InBuffer, |
| _In_ ULONG InBufferLength, |
| _Out_writes_bytes_(*OutBufferLength) |
| PVOID OutBuffer, |
| _Inout_ PULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_SUCCESS; |
| |
| UNREFERENCED_PARAMETER(OutBuffer); |
| *OutBufferLength = 0; |
| |
| if (InBufferLength >= sizeof(uint8_t) + sizeof(otExtAddress)) |
| { |
| const ULONG aPSKdBufferLength = InBufferLength - sizeof(uint8_t) - sizeof(otExtAddress) - sizeof(uint32_t); |
| |
| if (aPSKdBufferLength <= OPENTHREAD_PSK_MAX_LENGTH + 1) |
| { |
| uint8_t aExtAddressValid = *(uint8_t*)InBuffer; |
| const otExtAddress *aExtAddress = aExtAddressValid == 0 ? NULL : (otExtAddress*)(InBuffer + sizeof(uint8_t)); |
| char *aPSKd = (char*)(InBuffer + sizeof(uint8_t) + sizeof(otExtAddress)); |
| uint32_t aTimeout = *(uint32_t*)(InBuffer + sizeof(uint8_t) + sizeof(otExtAddress) + aPSKdBufferLength); |
| |
| // Ensure aPSKd is NULL terminated in the buffer |
| if (strnlen(aPSKd, aPSKdBufferLength) < aPSKdBufferLength) |
| { |
| status = ThreadErrorToNtstatus(otCommissionerAddJoiner( |
| pFilter->otCtx, aExtAddress, aPSKd, aTimeout)); |
| } |
| } |
| } |
| |
| return status; |
| } |
| |
| _IRQL_requires_max_(PASSIVE_LEVEL) |
| NTSTATUS |
| otLwfIoCtl_otCommissionerRemoveJoiner( |
| _In_ PMS_FILTER pFilter, |
| _In_reads_bytes_(InBufferLength) |
| PUCHAR InBuffer, |
| _In_ ULONG InBufferLength, |
| _Out_writes_bytes_(*OutBufferLength) |
| PVOID OutBuffer, |
| _Inout_ PULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_SUCCESS; |
| |
| UNREFERENCED_PARAMETER(OutBuffer); |
| *OutBufferLength = 0; |
| |
| if (InBufferLength >= sizeof(uint8_t) + sizeof(otExtAddress)) |
| { |
| uint8_t aExtAddressValid = *(uint8_t*)InBuffer; |
| const otExtAddress *aExtAddress = aExtAddressValid == 0 ? NULL : (otExtAddress*)(InBuffer + sizeof(uint8_t)); |
| status = ThreadErrorToNtstatus(otCommissionerRemoveJoiner( |
| pFilter->otCtx, aExtAddress)); |
| } |
| |
| return status; |
| } |
| |
| _IRQL_requires_max_(PASSIVE_LEVEL) |
| NTSTATUS |
| otLwfIoCtl_otCommissionerProvisioningUrl( |
| _In_ PMS_FILTER pFilter, |
| _In_reads_bytes_(InBufferLength) |
| PUCHAR InBuffer, |
| _In_ ULONG InBufferLength, |
| _Out_writes_bytes_(*OutBufferLength) |
| PVOID OutBuffer, |
| _Inout_ PULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_SUCCESS; |
| |
| UNREFERENCED_PARAMETER(OutBuffer); |
| *OutBufferLength = 0; |
| |
| if (InBufferLength <= OPENTHREAD_PROV_URL_MAX_LENGTH + 1) |
| { |
| char *aProvisioningUrl = InBufferLength > 1 ? (char*)InBuffer : NULL; |
| |
| // Ensure aProvisioningUrl is empty or NULL terminated in the buffer |
| if (aProvisioningUrl == NULL || |
| strnlen(aProvisioningUrl, InBufferLength) < InBufferLength) |
| { |
| status = ThreadErrorToNtstatus(otCommissionerSetProvisioningUrl( |
| pFilter->otCtx, aProvisioningUrl)); |
| } |
| } |
| |
| return status; |
| } |
| |
| _IRQL_requires_max_(PASSIVE_LEVEL) |
| NTSTATUS |
| otLwfIoCtl_otCommissionerAnnounceBegin( |
| _In_ PMS_FILTER pFilter, |
| _In_reads_bytes_(InBufferLength) |
| PUCHAR InBuffer, |
| _In_ ULONG InBufferLength, |
| _Out_writes_bytes_(*OutBufferLength) |
| PVOID OutBuffer, |
| _Inout_ PULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_INVALID_PARAMETER; |
| |
| *OutBufferLength = 0; |
| UNREFERENCED_PARAMETER(OutBuffer); |
| |
| if (InBufferLength >= sizeof(uint32_t) + sizeof(uint8_t) + sizeof(uint16_t) + sizeof(otIp6Address)) |
| { |
| uint32_t aChannelMask = *(uint32_t*)InBuffer; |
| uint8_t aCount = *(uint8_t*)(InBuffer + sizeof(uint32_t)); |
| uint16_t aPeriod = *(uint16_t*)(InBuffer + sizeof(uint32_t) + sizeof(uint8_t)); |
| const otIp6Address *aAddress = (otIp6Address*)(InBuffer + sizeof(uint32_t) + sizeof(uint8_t) + sizeof(uint16_t)); |
| |
| if (InBufferLength >= sizeof(otIp6Address) + sizeof(uint8_t) + aCount) |
| { |
| status = ThreadErrorToNtstatus( |
| otCommissionerAnnounceBegin( |
| pFilter->otCtx, |
| aChannelMask, |
| aCount, |
| aPeriod, |
| aAddress) |
| ); |
| } |
| } |
| |
| return status; |
| } |
| |
| _IRQL_requires_max_(PASSIVE_LEVEL) |
| NTSTATUS |
| otLwfIoCtl_otSendActiveGet( |
| _In_ PMS_FILTER pFilter, |
| _In_reads_bytes_(InBufferLength) |
| PUCHAR InBuffer, |
| _In_ ULONG InBufferLength, |
| _Out_writes_bytes_(*OutBufferLength) |
| PVOID OutBuffer, |
| _Inout_ PULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_INVALID_PARAMETER; |
| |
| *OutBufferLength = 0; |
| UNREFERENCED_PARAMETER(OutBuffer); |
| |
| if (InBufferLength >= sizeof(uint8_t)) |
| { |
| uint8_t aLength = *(uint8_t*)InBuffer; |
| PUCHAR aTlvTypes = aLength == 0 ? NULL : InBuffer + sizeof(uint8_t); |
| |
| if (InBufferLength >= sizeof(uint8_t) + aLength) |
| { |
| otIp6Address *aAddress = NULL; |
| if (InBufferLength >= sizeof(uint8_t) + aLength + sizeof(otIp6Address)) |
| aAddress = (otIp6Address*)(InBuffer + sizeof(uint8_t) + aLength); |
| |
| status = ThreadErrorToNtstatus( |
| otDatasetSendMgmtActiveGet( |
| pFilter->otCtx, |
| aTlvTypes, |
| aLength, |
| aAddress) |
| ); |
| } |
| } |
| |
| return status; |
| } |
| |
| _IRQL_requires_max_(PASSIVE_LEVEL) |
| NTSTATUS |
| otLwfIoCtl_otSendActiveSet( |
| _In_ PMS_FILTER pFilter, |
| _In_reads_bytes_(InBufferLength) |
| PUCHAR InBuffer, |
| _In_ ULONG InBufferLength, |
| _Out_writes_bytes_(*OutBufferLength) |
| PVOID OutBuffer, |
| _Inout_ PULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_INVALID_PARAMETER; |
| |
| *OutBufferLength = 0; |
| UNREFERENCED_PARAMETER(OutBuffer); |
| |
| if (InBufferLength >= sizeof(otOperationalDataset) + sizeof(uint8_t)) |
| { |
| const otOperationalDataset *aDataset = (otOperationalDataset*)InBuffer; |
| uint8_t aLength = *(uint8_t*)(InBuffer + sizeof(otOperationalDataset)); |
| PUCHAR aTlvTypes = aLength == 0 ? NULL : InBuffer + sizeof(otOperationalDataset) + sizeof(uint8_t); |
| |
| if (InBufferLength >= sizeof(otOperationalDataset) + sizeof(uint8_t) + aLength) |
| { |
| status = ThreadErrorToNtstatus( |
| otDatasetSendMgmtActiveSet( |
| pFilter->otCtx, |
| aDataset, |
| aTlvTypes, |
| aLength) |
| ); |
| } |
| } |
| |
| return status; |
| } |
| |
| _IRQL_requires_max_(PASSIVE_LEVEL) |
| NTSTATUS |
| otLwfIoCtl_otSendPendingGet( |
| _In_ PMS_FILTER pFilter, |
| _In_reads_bytes_(InBufferLength) |
| PUCHAR InBuffer, |
| _In_ ULONG InBufferLength, |
| _Out_writes_bytes_(*OutBufferLength) |
| PVOID OutBuffer, |
| _Inout_ PULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_INVALID_PARAMETER; |
| |
| *OutBufferLength = 0; |
| UNREFERENCED_PARAMETER(OutBuffer); |
| |
| if (InBufferLength >= sizeof(uint8_t)) |
| { |
| uint8_t aLength = *(uint8_t*)InBuffer; |
| PUCHAR aTlvTypes = aLength == 0 ? NULL : InBuffer + sizeof(uint8_t); |
| |
| if (InBufferLength >= sizeof(uint8_t) + aLength) |
| { |
| otIp6Address *aAddress = NULL; |
| if (InBufferLength >= sizeof(uint8_t) + aLength + sizeof(otIp6Address)) |
| aAddress = (otIp6Address*)(InBuffer + sizeof(uint8_t) + aLength); |
| |
| status = ThreadErrorToNtstatus( |
| otDatasetSendMgmtPendingGet( |
| pFilter->otCtx, |
| aTlvTypes, |
| aLength, |
| aAddress) |
| ); |
| } |
| } |
| |
| return status; |
| } |
| |
| _IRQL_requires_max_(PASSIVE_LEVEL) |
| NTSTATUS |
| otLwfIoCtl_otSendPendingSet( |
| _In_ PMS_FILTER pFilter, |
| _In_reads_bytes_(InBufferLength) |
| PUCHAR InBuffer, |
| _In_ ULONG InBufferLength, |
| _Out_writes_bytes_(*OutBufferLength) |
| PVOID OutBuffer, |
| _Inout_ PULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_INVALID_PARAMETER; |
| |
| *OutBufferLength = 0; |
| UNREFERENCED_PARAMETER(OutBuffer); |
| |
| if (InBufferLength >= sizeof(otOperationalDataset) + sizeof(uint8_t)) |
| { |
| const otOperationalDataset *aDataset = (otOperationalDataset*)InBuffer; |
| uint8_t aLength = *(uint8_t*)(InBuffer + sizeof(otOperationalDataset)); |
| PUCHAR aTlvTypes = aLength == 0 ? NULL : InBuffer + sizeof(otOperationalDataset) + sizeof(uint8_t); |
| |
| if (InBufferLength >= sizeof(otOperationalDataset) + sizeof(uint8_t) + aLength) |
| { |
| status = ThreadErrorToNtstatus( |
| otDatasetSendMgmtPendingSet( |
| pFilter->otCtx, |
| aDataset, |
| aTlvTypes, |
| aLength) |
| ); |
| } |
| } |
| |
| return status; |
| } |
| |
| _IRQL_requires_max_(PASSIVE_LEVEL) |
| NTSTATUS |
| otLwfIoCtl_otSendMgmtCommissionerGet( |
| _In_ PMS_FILTER pFilter, |
| _In_reads_bytes_(InBufferLength) |
| PUCHAR InBuffer, |
| _In_ ULONG InBufferLength, |
| _Out_writes_bytes_(*OutBufferLength) |
| PVOID OutBuffer, |
| _Inout_ PULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_INVALID_PARAMETER; |
| |
| *OutBufferLength = 0; |
| UNREFERENCED_PARAMETER(OutBuffer); |
| |
| if (InBufferLength >= sizeof(uint8_t)) |
| { |
| uint8_t aLength = *(uint8_t*)InBuffer; |
| PUCHAR aTlvs = aLength == 0 ? NULL : InBuffer + sizeof(uint8_t); |
| |
| if (InBufferLength >= sizeof(uint8_t) + aLength) |
| { |
| status = ThreadErrorToNtstatus( |
| otCommissionerSendMgmtGet( |
| pFilter->otCtx, |
| aTlvs, |
| aLength) |
| ); |
| } |
| } |
| |
| return status; |
| } |
| |
| _IRQL_requires_max_(PASSIVE_LEVEL) |
| NTSTATUS |
| otLwfIoCtl_otSendMgmtCommissionerSet( |
| _In_ PMS_FILTER pFilter, |
| _In_reads_bytes_(InBufferLength) |
| PUCHAR InBuffer, |
| _In_ ULONG InBufferLength, |
| _Out_writes_bytes_(*OutBufferLength) |
| PVOID OutBuffer, |
| _Inout_ PULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_INVALID_PARAMETER; |
| |
| *OutBufferLength = 0; |
| UNREFERENCED_PARAMETER(OutBuffer); |
| |
| if (InBufferLength >= sizeof(otCommissioningDataset) + sizeof(uint8_t)) |
| { |
| const otCommissioningDataset *aDataset = (otCommissioningDataset*)InBuffer; |
| uint8_t aLength = *(uint8_t*)(InBuffer + sizeof(otCommissioningDataset)); |
| PUCHAR aTlvs = aLength == 0 ? NULL : InBuffer + sizeof(otCommissioningDataset) + sizeof(uint8_t); |
| |
| if (InBufferLength >= sizeof(otCommissioningDataset) + sizeof(uint8_t) + aLength) |
| { |
| status = ThreadErrorToNtstatus( |
| otCommissionerSendMgmtSet( |
| pFilter->otCtx, |
| aDataset, |
| aTlvs, |
| aLength) |
| ); |
| } |
| } |
| |
| return status; |
| } |
| |
| _IRQL_requires_max_(PASSIVE_LEVEL) |
| NTSTATUS |
| otLwfIoCtl_otKeySwitchGuardtime( |
| _In_ PMS_FILTER pFilter, |
| _In_reads_bytes_(InBufferLength) |
| PUCHAR InBuffer, |
| _In_ ULONG InBufferLength, |
| _Out_writes_bytes_(*OutBufferLength) |
| PVOID OutBuffer, |
| _Inout_ PULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_INVALID_PARAMETER; |
| |
| if (InBufferLength >= sizeof(uint32_t)) |
| { |
| otThreadSetKeySwitchGuardTime(pFilter->otCtx, *(uint32_t*)InBuffer); |
| status = STATUS_SUCCESS; |
| *OutBufferLength = 0; |
| } |
| else if (*OutBufferLength >= sizeof(uint32_t)) |
| { |
| *(uint32_t*)OutBuffer = otThreadGetKeySwitchGuardTime(pFilter->otCtx); |
| status = STATUS_SUCCESS; |
| *OutBufferLength = sizeof(uint32_t); |
| } |
| else |
| { |
| *OutBufferLength = 0; |
| } |
| |
| return status; |
| } |
| |
| _IRQL_requires_max_(PASSIVE_LEVEL) |
| NTSTATUS |
| otLwfTunIoCtl_otKeySwitchGuardtime( |
| _In_ PMS_FILTER pFilter, |
| _In_ PIRP pIrp, |
| _In_reads_bytes_(InBufferLength) |
| PUCHAR InBuffer, |
| _In_ ULONG InBufferLength, |
| _In_ ULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_INVALID_PARAMETER; |
| |
| if (InBufferLength >= sizeof(uint32_t)) |
| { |
| status = |
| otLwfTunSendCommandForIrp( |
| pFilter, |
| pIrp, |
| NULL, |
| SPINEL_CMD_PROP_VALUE_SET, |
| SPINEL_PROP_NET_KEY_SWITCH_GUARDTIME, |
| sizeof(uint32_t), |
| SPINEL_DATATYPE_UINT32_S, |
| *(uint32_t*)InBuffer); |
| } |
| else if (OutBufferLength >= sizeof(uint32_t)) |
| { |
| status = |
| otLwfTunSendCommandForIrp( |
| pFilter, |
| pIrp, |
| otLwfTunIoCtl_otKeySwitchGuardtime_Handler, |
| SPINEL_CMD_PROP_VALUE_GET, |
| SPINEL_PROP_NET_KEY_SWITCH_GUARDTIME, |
| 0, |
| NULL); |
| } |
| |
| return status; |
| } |
| |
| _IRQL_requires_max_(DISPATCH_LEVEL) |
| NTSTATUS |
| otLwfTunIoCtl_otKeySwitchGuardtime_Handler( |
| _In_ spinel_prop_key_t Key, |
| _In_reads_bytes_(DataLength) const uint8_t* Data, |
| _In_ spinel_size_t DataLength, |
| _Out_writes_bytes_(*OutBufferLength) |
| PVOID OutBuffer, |
| _Inout_ PULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_INVALID_PARAMETER; |
| if (Key == SPINEL_PROP_NET_KEY_SWITCH_GUARDTIME) |
| { |
| if (try_spinel_datatype_unpack(Data, DataLength, SPINEL_DATATYPE_UINT32_S, (uint32_t*)OutBuffer)) |
| { |
| *OutBufferLength = sizeof(uint32_t); |
| status = STATUS_SUCCESS; |
| } |
| } |
| return status; |
| } |
| |
| _IRQL_requires_max_(PASSIVE_LEVEL) |
| NTSTATUS |
| otLwfIoCtl_otThreadAutoStart( |
| _In_ PMS_FILTER pFilter, |
| _In_reads_bytes_(InBufferLength) |
| PUCHAR InBuffer, |
| _In_ ULONG InBufferLength, |
| _Out_writes_bytes_(*OutBufferLength) |
| PVOID OutBuffer, |
| _Inout_ PULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_INVALID_PARAMETER; |
| |
| if (InBufferLength >= sizeof(BOOLEAN)) |
| { |
| status = |
| ThreadErrorToNtstatus( |
| otThreadSetAutoStart( |
| pFilter->otCtx, |
| *(BOOLEAN*)InBuffer != FALSE) |
| ); |
| *OutBufferLength = 0; |
| } |
| else if (*OutBufferLength >= sizeof(BOOLEAN)) |
| { |
| *(BOOLEAN*)OutBuffer = otThreadGetAutoStart(pFilter->otCtx) ? TRUE : FALSE; |
| *OutBufferLength = sizeof(BOOLEAN); |
| status = STATUS_SUCCESS; |
| } |
| else |
| { |
| *OutBufferLength = 0; |
| } |
| |
| return status; |
| } |
| |
| _IRQL_requires_max_(PASSIVE_LEVEL) |
| NTSTATUS |
| otLwfIoCtl_otThreadPreferredRouterId( |
| _In_ PMS_FILTER pFilter, |
| _In_reads_bytes_(InBufferLength) |
| PUCHAR InBuffer, |
| _In_ ULONG InBufferLength, |
| _Out_writes_bytes_(*OutBufferLength) |
| PVOID OutBuffer, |
| _Inout_ PULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_INVALID_PARAMETER; |
| |
| *OutBufferLength = 0; |
| UNREFERENCED_PARAMETER(OutBuffer); |
| |
| if (InBufferLength >= sizeof(uint8_t)) |
| { |
| status = |
| ThreadErrorToNtstatus( |
| otThreadSetPreferredRouterId( |
| pFilter->otCtx, |
| *(uint8_t*)InBuffer != FALSE) |
| ); |
| *OutBufferLength = 0; |
| } |
| |
| return status; |
| } |
| |
| _IRQL_requires_max_(PASSIVE_LEVEL) |
| NTSTATUS |
| otLwfIoCtl_otParentPriority( |
| _In_ PMS_FILTER pFilter, |
| _In_reads_bytes_(InBufferLength) |
| PUCHAR InBuffer, |
| _In_ ULONG InBufferLength, |
| _Out_writes_bytes_(*OutBufferLength) |
| PVOID OutBuffer, |
| _Inout_ PULONG OutBufferLength |
| ) |
| { |
| NTSTATUS status = STATUS_INVALID_PARAMETER; |
| |
| if (InBufferLength >= sizeof(int8_t)) |
| { |
| otThreadSetParentPriority(pFilter->otCtx, *(int8_t*)InBuffer); |
| status = STATUS_SUCCESS; |
| *OutBufferLength = 0; |
| } |
| else if (*OutBufferLength >= sizeof(int8_t)) |
| { |
| *(uint16_t*)OutBuffer = otThreadGetParentPriority(pFilter->otCtx); |
| status = STATUS_SUCCESS; |
| *OutBufferLength = sizeof(int8_t); |
| } |
| else |
| { |
| *OutBufferLength = 0; |
| } |
| |
| return status; |
| } |
| |