Exemplo n.º 1
0
spinel_status_t
spinel_datatype_iter_open_container(const spinel_datatype_iter_t* iter, spinel_datatype_iter_t* subiter)
{
	spinel_status_t ret = SPINEL_STATUS_PARSE_ERROR;
	int depth = 0;
	spinel_ssize_t block_len;

	require(iter->data_len > 2, bail);

	if ((spinel_datatype_t)*iter->pack_format == SPINEL_DATATYPE_ARRAY_C) {
		ret = SPINEL_STATUS_UNIMPLEMENTED;
		goto bail;
	}

	if ((spinel_datatype_t)*iter->pack_format != SPINEL_DATATYPE_STRUCT_C) {
		ret = SPINEL_STATUS_PARSE_ERROR;
		goto bail;
	}

	*subiter = *iter;

	require(subiter->pack_format[1] == '(', bail);

	subiter->container = iter->pack_format[0];
	subiter->pack_format += 2;

	do {
		switch(subiter->pack_format[1]) {
		case '(': depth++; break;
		case ')': depth++; break;
		case 0: depth = 0; break;
		}
	} while(depth > 0);

	require(subiter->pack_format[1] == ')', bail);
	subiter->pack_format += 2;

	block_len = spinel_datatype_unpack(
		subiter->data_ptr,
		subiter->data_len,
		SPINEL_DATATYPE_DATA_WLEN_S,
		&subiter->data_ptr,
		&subiter->data_len
	);

	require(block_len > 0, bail);

	ret = SPINEL_STATUS_OK;

bail:
	return ret;
}
Exemplo n.º 2
0
_Use_decl_annotations_
NDIS_STATUS
FilterRestart(
    NDIS_HANDLE                     FilterModuleContext,
    PNDIS_FILTER_RESTART_PARAMETERS RestartParameters
    )
/*++

Routine Description:

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

Arguments:

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

Return Value:

    NDIS_STATUS_SUCCESS: if filter restarts successfully
    NDIS_STATUS_XXX: Otherwise.

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

    PNDIS_RESTART_GENERAL_ATTRIBUTES NdisGeneralAttributes;
    PNDIS_RESTART_ATTRIBUTES         NdisRestartAttributes;

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

    NT_ASSERT(pFilter->State == FilterPaused);

    NdisRestartAttributes = RestartParameters->RestartAttributes;

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

        NdisGeneralAttributes = (PNDIS_RESTART_GENERAL_ATTRIBUTES)NdisRestartAttributes->Data;

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

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

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

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

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

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

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

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

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

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

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

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

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

exit:

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

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

        pFilter->DeviceStatus = OTLWF_DEVICE_STATUS_UNINTIALIZED;

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

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

    LogFuncExitNDIS(DRIVER_DEFAULT, NdisStatus);
    return NdisStatus;
}
Exemplo n.º 3
0
spinel_status_t
spinel_datatype_iter_next(spinel_datatype_iter_t* iter)
{
	spinel_status_t ret = SPINEL_STATUS_PARSE_ERROR;
	spinel_datatype_iter_t scratchpad = *iter;
	const char* next_pack_format;

	if (!iter->data_ptr || !iter->data_len || !iter->pack_format) {
		ret = SPINEL_STATUS_EMPTY;
		goto bail;
	}

	next_pack_format = spinel_next_packed_datatype(scratchpad.pack_format);

	switch ((spinel_datatype_t)*scratchpad.pack_format) {
	case SPINEL_DATATYPE_INT8_C:
	case SPINEL_DATATYPE_UINT8_C:
		require(scratchpad.data_len >= sizeof(uint8_t), bail);
		scratchpad.data_ptr += sizeof(uint8_t);
		scratchpad.data_len -= sizeof(uint8_t);
		break;

	case SPINEL_DATATYPE_INT16_C:
	case SPINEL_DATATYPE_UINT16_C:
		require(scratchpad.data_len >= sizeof(uint16_t), bail);
		scratchpad.data_ptr += sizeof(uint16_t);
		scratchpad.data_len -= sizeof(uint16_t);
		break;

	case SPINEL_DATATYPE_INT32_C:
	case SPINEL_DATATYPE_UINT32_C:
		require(scratchpad.data_len >= sizeof(uint32_t), bail);
		scratchpad.data_ptr += sizeof(uint32_t);
		scratchpad.data_len -= sizeof(uint32_t);
		break;

	case SPINEL_DATATYPE_IPv6ADDR_C:
		require(scratchpad.data_len >= sizeof(spinel_ipv6addr_t), bail);
		scratchpad.data_ptr += sizeof(spinel_ipv6addr_t);
		scratchpad.data_len -= sizeof(spinel_ipv6addr_t);
		break;

	case SPINEL_DATATYPE_EUI64_C:
		require(scratchpad.data_len >= sizeof(spinel_eui64_t), bail);
		scratchpad.data_ptr += sizeof(spinel_eui64_t);
		scratchpad.data_len -= sizeof(spinel_eui64_t);
		break;

	case SPINEL_DATATYPE_EUI48_C:
		require(scratchpad.data_len >= sizeof(spinel_eui48_t), bail);
		scratchpad.data_ptr += sizeof(spinel_eui48_t);
		scratchpad.data_len -= sizeof(spinel_eui48_t);
		break;

	case SPINEL_DATATYPE_UINT_PACKED_C:
		{
			spinel_ssize_t pui_len = spinel_packed_uint_decode(scratchpad.data_ptr, scratchpad.data_len, NULL);
			require(pui_len > 0, bail);
			scratchpad.data_ptr += pui_len;
			scratchpad.data_len -= pui_len;
		}
		break;


	case SPINEL_DATATYPE_UTF8_C:
		{
			size_t str_len = strnlen((const char*)scratchpad.data_ptr, scratchpad.data_len) + 1;
			scratchpad.data_ptr += str_len;
			scratchpad.data_len -= str_len;
		}
		break;

	case SPINEL_DATATYPE_ARRAY_C:
	case SPINEL_DATATYPE_DATA_C:
		if ( (scratchpad.pack_format[1] == ')')
		  || (next_pack_format == 0)
		) {
			// Special case: This type is size of the rest of the buffer!
			scratchpad.data_ptr += scratchpad.data_len;
			scratchpad.data_len -= scratchpad.data_len;
			break;
		}

		// Fall through to length-prepended...
	case SPINEL_DATATYPE_STRUCT_C:
	case SPINEL_DATATYPE_DATA_WLEN_C:
		{
			spinel_ssize_t block_len = spinel_datatype_unpack(
				scratchpad.data_ptr,
				scratchpad.data_len,
				SPINEL_DATATYPE_STRUCT_S("")
			);

			require(block_len > 0, bail);
			require(block_len < SPINEL_FRAME_MAX_SIZE, bail);
			require(scratchpad.data_len >= block_len, bail);

			scratchpad.data_ptr += block_len;
			scratchpad.data_len -= block_len;

		}
		break;

	default:
		// Unsupported Type!
		goto bail;
	}

	scratchpad.pack_format = next_pack_format;

	while (scratchpad.pack_format[0] == SPINEL_DATATYPE_VOID_C) {
		scratchpad.pack_format++;
	}

	if ((*scratchpad.pack_format == ')')
	 || (*scratchpad.pack_format == 0)
	 || (scratchpad.data_len == 0)
	) {
		ret = SPINEL_STATUS_EMPTY;
	} else {
		ret = SPINEL_STATUS_OK;
	}

	if (iter->container == SPINEL_DATATYPE_ARRAY_C) {
		iter->data_ptr = scratchpad.data_ptr;
		iter->data_len = scratchpad.data_len;
	} else {
		*iter = scratchpad;
	}

bail:
	return ret;
}